⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mae_be.c

📁 AU1200嵌入式处理器媒体加速引擎(mae)的驱动
💻 C
字号:
#include "mae_global.h"
#include "mae_be.h"
#include "queue.h"
#include "mae_memory.h"
#include <windows.h>

#define LUTSIZE   32

// It was found that (with some WMV cert clips) when the encoded height is 496 (and when we 
// scale it down to 480 for display) the MAE-BE would fail to generate an interruput. The
// problem was with the VSR not getting programmed with the right fractional value. (Also
// the issue could be reproduced across codecs). Defining ADJUST_HV_RATIO_ALWAYS fixes that.
#define ADJUST_HV_RATIO_ALWAYS

extern AU1200_LCD lcd_info;

extern UINT32 video_out_rotation;  // default, no rotation
RECT g_RectPlayer;
RECT g_RectScreen;

UINT32 csc_matrix[12] = 
{
  0x04a7, 0x0000, 0x0662,
  0x04a7, 0x1191, 0x1340,
  0x04a7, 0x0811, 0x0000,
  0xf211, 0x0879, 0xeeb3
};


UINT32 glut[LUTSIZE] = 
{
  0x00033a03, 0x00043903, 0x00053902, 0x00063802, 
  0x00073801, 0x00083701, 0x00093601, 0x000b3401, 
  0x000c3400, 0x000e3200, 0x000f3100, 0x00112f00, 
  0x00132d00, 0x00162a00, 0x00182800, 0x001a2600, 
  0x001d2300, 0x001f2100, 0x00211f00, 0x00241c00, 
  0x00261a00, 0x00291700, 0x002b1500, 0x002d1300, 
  0x00301000, 0x01320d00, 0x01330c00, 0x01350a00, 
  0x01360900, 0x02370700, 0x02380600, 0x03380500
};


void program_static_be_registers(void) 
{
  UINT32 reg;
  UINT32 i;
  
  program_lut();
  
  // CSC
  for (i=0, reg=MAEBE_CSCMATRIX; i<12; i++, reg+=4) 
  {
    au_writel(csc_matrix[i], reg);
  }
  
    // Use the alpha plane for 32 BPP    
  if ((SIZE_RGB_BPP == 32) || (SIZE_RGB_BPP == 24))
  {
    au_writel(0xFF, MAEBE_CSCALPHA);
  }
  else
  {
    au_writel(0, MAEBE_CSCALPHA);    
  }
}

void dump_lcd_registers(void) 
{
  
  DPRINTF(MSG_BE, (TEXT("backcolor\t%08X\n"), lcd->backcolor));
  
  DPRINTF(MSG_BE, (TEXT("ColorKey\t%08X\tmask\t%08X\n"), lcd->colorkey, lcd->colorkeymsk));
  
  DPRINTF(MSG_BE, (TEXT("Alpha      \t%d \t%d\n"), 
    ((lcd->window[0].winctrl0 >> 2) & 0x1ff), ((lcd->window[MAE_PLANE].winctrl0 >> 2) & 0x1ff)));
  DPRINTF(MSG_BE, (TEXT("Plane alpha override\t%d \t%d\n"), 
    ((lcd->window[0].winctrl0 >> 1) & 0x1), ((lcd->window[MAE_PLANE].winctrl0 >> 1) & 0x1)));
  
  DPRINTF(MSG_BE, (TEXT("priority    \t%d \t%d\n"), 
    (lcd->window[0].winctrl1 >> 30), (lcd->window[MAE_PLANE].winctrl1 >> 30)));
  DPRINTF(MSG_BE, (TEXT("channel    \t%d \t%d\n"), 
    ((lcd->window[0].winctrl1 >> 29) & 0x1), ((lcd->window[MAE_PLANE].winctrl1 >> 29) & 0x1)));
  DPRINTF(MSG_BE, (TEXT("Xsiz    \t%d \t%d \n"), 
    ((lcd->window[0].winctrl1 >> 11) & 0x7ff), ((lcd->window[MAE_PLANE].winctrl1 >> 11) & 0x7ff)));
  DPRINTF(MSG_BE, (TEXT("Ysiz    \t%d \t%d\n"), 
    ((lcd->window[0].winctrl1) & 0x7ff), ((lcd->window[MAE_PLANE].winctrl1) & 0x7ff)));
  
  DPRINTF(MSG_BE, (TEXT("format    \t%d \t%d \n"), 
    ((lcd->window[0].winctrl1 >> 25) & 0xF), ((lcd->window[MAE_PLANE].winctrl1 >> 25) & 0xF)));
  DPRINTF(MSG_BE, (TEXT("cco\t\t%d \t%d \n"), 
    ((lcd->window[0].winctrl1 >> 24) & 0x1), ((lcd->window[MAE_PLANE].winctrl1 >> 24) & 0x1)));
  DPRINTF(MSG_BE, (TEXT("pixel order\t%d \t%d\n"), 
    ((lcd->window[0].winctrl1 >> 22) & 0x3), ((lcd->window[MAE_PLANE].winctrl1 >> 22) & 0x3)));
  
  DPRINTF(MSG_BE, (TEXT("keymode    \t%d \t%d\n"), 
    ((lcd->window[0].winctrl2 >> 24) & 0x3), ((lcd->window[MAE_PLANE].winctrl2 >> 24) & 0x3)));
}

void dump_be_registers(void) {

  DPRINTF(MSG_BE, (TEXT("MAEBE_SRCASTR \t%d\n"), au_readl(MAEBE_SRCASTR)));
  DPRINTF(MSG_BE, (TEXT("MAEBE_SRCBSTR \t%d\n"), au_readl(MAEBE_SRCBSTR)));
  DPRINTF(MSG_BE, (TEXT("MAEBE_SRCCSTR \t%d\n"), au_readl(MAEBE_SRCCSTR)));
  DPRINTF(MSG_BE, (TEXT("MAEBE_SRCFHW \t%08X, %d x %d\n"), 
    au_readl(MAEBE_SRCFHW), au_readl(MAEBE_SRCFHW) & 0x7FF, au_readl(MAEBE_SRCFHW) >> 16));

  DPRINTF(MSG_BE, (TEXT("MAEBE_SRCCFG \t%08X\n"), au_readl(MAEBE_SRCCFG)));

  DPRINTF(MSG_BE, (TEXT("MAEBE_DSTCFG \t%08X, OF %d\n"), 
    au_readl(MAEBE_DSTCFG), (au_readl(MAEBE_DSTCFG) >> 2) & 0x3));


  DPRINTF(MSG_BE, (TEXT("MAEBE_DSTSTR \t%d bytes\n"), au_readl(MAEBE_DSTSTR)));
  DPRINTF(MSG_BE, (TEXT("MAEBE_DSTHEIGHT \t%d lines\n"), au_readl(MAEBE_DSTHEIGHT)));
  DPRINTF(MSG_BE, (TEXT("MAEBE_SCFHSR \t%08X\n"), au_readl(MAEBE_SCFHSR)));
  DPRINTF(MSG_BE, (TEXT("MAEBE_SCFVSR \t%08X\n"), au_readl(MAEBE_SCFVSR)));

}

void ring_be_doorbell(void) 
{
  au_writel(MAEBE_CTLFPC_START, MAEBE_CTLFPC);
}

void program_be_regs(PMAEQ_T pmaeq, PRGBQ_T prgbq) 
{
  //reads overlay hardware, setups mae backend destination
  UINT32 yy, uu, vv;
  UINT32 hsr, vsr, rgb,iSourceFrameWidth, iSourceFrameHeight;
  static UINT32 prev_width=0, prev_height=0;
  RECT RectCrop;
  UINT32 bytespp;
    
  DPRINTF(MSG_FUNCTION, (TEXT("program_be_regs entry\n")));

  // read the current window settings (ddraw changes these through user events)
  prgbq->x = ((lcd->window[MAE_PLANE].winctrl0 >> 21) & 0x7ff);
  prgbq->y = ((lcd->window[MAE_PLANE].winctrl0 >> 10) & 0x7ff);
  prgbq->w = ((lcd->window[MAE_PLANE].winctrl1 >> 11) & 0x7ff) + 1;
  prgbq->h = ((lcd->window[MAE_PLANE].winctrl1) & 0x7ff) + 1;
  
  if ((prgbq->w != prev_width) || (prgbq->h != prev_height)) 
  {
    prev_width = prgbq->w;
    prev_height = prgbq->h;
    
    DPRINTF(MSG_BE, (TEXT("program_be_regs:  overlay window %dx%d @ (%d,%d)\n"), 
      prgbq->w, prgbq->h, prgbq->x, prgbq->y));
    
#if (MSG_BE == 1)
    dump_lcd_registers();
#endif
  }
  
  DPRINTF(MSG_BE, (TEXT("program_be_regs: pmaeq->y %x\n"),pmaeq->y));
  
  yy = MAE_PADDR((UINT32)pmaeq->y);
  uu = MAE_PADDR((UINT32)pmaeq->u);
  vv = MAE_PADDR((UINT32)pmaeq->v);
    
  // Check if the decoder(s) set this field. If so, its asking to chop off
  // portions of the right edge of the frame. If not, use the default
  if (pmaeq->chopped_picture_linesize)
    iSourceFrameWidth = pmaeq->chopped_picture_linesize;
  else
    iSourceFrameWidth = pmaeq->encoded_picture_linesize;
  
  // Check if the decoder(s) set this field. If so, its asking to chop off
  // portions of the bottom edge of the frame. If not, use the default
  if (pmaeq->chopped_picture_height)
    iSourceFrameHeight = pmaeq->chopped_picture_height;
  else
    iSourceFrameHeight = pmaeq->encoded_picture_height;

  // crop the source image
  RectCrop.left = 0;
  RectCrop.top = 0;
  RectCrop.right = iSourceFrameWidth;
  RectCrop.bottom = iSourceFrameHeight;

  if (g_RectPlayer.right > g_RectScreen.right) 
  {
    RectCrop.right = (iSourceFrameWidth * 
      (g_RectScreen.right-g_RectPlayer.left) / 
      (g_RectPlayer.right-g_RectPlayer.left)) & 0x7F0;
  }
  if (g_RectPlayer.bottom > g_RectScreen.bottom) 
  {
    RectCrop.bottom = (iSourceFrameHeight * 
      (g_RectScreen.bottom-g_RectPlayer.top) / 
      (g_RectPlayer.bottom-g_RectPlayer.top)) & 0x7F0;
  }
  if ((int)g_RectPlayer.left < (int)g_RectScreen.left) 
  {
    RectCrop.left = (iSourceFrameWidth * 
      (g_RectScreen.left-g_RectPlayer.left) / 
      (g_RectPlayer.right-g_RectPlayer.left) + 15) & 0x7F0;
    yy += RectCrop.left;
    uu += RectCrop.left/2;
    vv += RectCrop.left/2;
  }
  if ((int)g_RectPlayer.top < (int)g_RectScreen.top) 
  {
    RectCrop.top = 
      (iSourceFrameHeight * 
      (g_RectScreen.top-g_RectPlayer.top) / 
      (g_RectPlayer.bottom-g_RectPlayer.top) + 15) & 0x7F0;
    yy += RectCrop.top*pmaeq->encoded_picture_linesize;
    uu += RectCrop.top*pmaeq->encoded_picture_linesize/2;
    vv += RectCrop.top*pmaeq->encoded_picture_linesize/2;    
  }
  
  DPRINTF(MSG_BE, (TEXT("iSourceFrame %dx%d  ovly %d,%d->%d,%d  player %d,%d->%d,%d  crop %d,%d->%d,%d\n"),
      iSourceFrameWidth, iSourceFrameHeight,
      prgbq->x, prgbq->y, (prgbq->x+prgbq->w), (prgbq->y+prgbq->h),
      g_RectPlayer.left,g_RectPlayer.top,g_RectPlayer.right,g_RectPlayer.bottom, 
      RectCrop.left,RectCrop.top,RectCrop.right,RectCrop.bottom));

  iSourceFrameWidth = (RectCrop.right-RectCrop.left);
  iSourceFrameHeight = (RectCrop.bottom-RectCrop.top);

  au_writel(((iSourceFrameHeight << 16) | iSourceFrameWidth),MAEBE_SRCFHW);
  au_writel(0, MAEBE_SRCCFG);  // Use Big Endian format

  // BE source registers
  au_writel(yy, MAEBE_SRCAADDR);
  au_writel(uu, MAEBE_SRCBADDR);
  au_writel(vv, MAEBE_SRCCADDR);
  // set the strides to be the true FE output size
  au_writel(pmaeq->encoded_picture_linesize, MAEBE_SRCASTR);
  au_writel(pmaeq->encoded_picture_linesize/2, MAEBE_SRCBSTR);
  au_writel(pmaeq->encoded_picture_linesize/2, MAEBE_SRCCSTR);
  
  // BE destination registers
  if ((SIZE_RGB_BPP == 32) || (SIZE_RGB_BPP == 24))
  {
    bytespp = 4;
    au_writel(MAEBE_DSTCFG_888A | (video_out_rotation << 5), MAEBE_DSTCFG); // use big endian format    
  }
  else
  {
    bytespp = 2;
    au_writel(MAEBE_DSTCFG_565 | (video_out_rotation << 5), MAEBE_DSTCFG); // use big endian format
  }
  
  rgb = MAE_PADDR((UINT32)pmaeq->rgb);
  if (video_out_rotation == 0x1)
    rgb += (prgbq->w - 8) * bytespp;
  else if (video_out_rotation == 0x2)
    rgb += prgbq->w * bytespp * prgbq->h - 
    (((20 * bytespp * prgbq->w) / iSourceFrameWidth) & (~(bytespp - 1)));
  else if (video_out_rotation == 0x3)
    rgb += prgbq->w * bytespp * (prgbq->h - 1);  
  au_writel(rgb , MAEBE_DSTADDR);
  au_writel(prgbq->w*bytespp, MAEBE_DSTSTR);
   
  if ((video_out_rotation & 0x1))
  {
    au_writel(prgbq->w, MAEBE_DSTHEIGHT);   
    hsr = iSourceFrameWidth * 65536 / prgbq->h;
    vsr = iSourceFrameHeight * 65536 / prgbq->w;
  } 
  else
  {
    au_writel(prgbq->h, MAEBE_DSTHEIGHT);    
    hsr = iSourceFrameWidth * 65536 / prgbq->w;
    vsr = iSourceFrameHeight * 65536 / prgbq->h;
  }

  DPRINTF(MSG_BE, (TEXT("ratios width %d / %d  height %d / %d \n"),
    iSourceFrameWidth, prgbq->w, iSourceFrameHeight, prgbq->h));  
  DPRINTF(MSG_BE, (TEXT("program_be_regs:  aspect  %d : %d\n"), 
    (pmaeq->aspect >> 16), (pmaeq->aspect & 0xffff)));
  DPRINTF(MSG_BE, (TEXT("program_be_regs:  hsr 0x%x, vsr 0x%x\n"), hsr, vsr));

#ifndef ADJUST_HV_RATIO_ALWAYS
    if (hsr & 0x7) 
#endif
  {
    hsr = (hsr & 0xfffffff8) + 0x8;
  }

#ifndef ADJUST_HV_RATIO_ALWAYS
    if (vsr & 0x7) 
#endif
  {
    vsr = (vsr & 0xfffffff8) + 0x8;
  }

  DPRINTF(MSG_BE, (TEXT("program_be_regs: picture %dx%d, chopped %dx%d, BE-input %dx%d, BE-output %dx%d\n"), 
    pmaeq->encoded_picture_linesize, pmaeq->encoded_picture_height,
    pmaeq->chopped_picture_linesize, pmaeq->chopped_picture_height,
    iSourceFrameWidth, iSourceFrameHeight, prgbq->w, prgbq->h));
  
  au_writel(hsr, MAEBE_SCFHSR);
  au_writel(vsr, MAEBE_SCFVSR);
  au_writel(0, MAEBE_SCFDISABLE); // enable the scf, set to 1 to bypass

#if (MSG_BE == 1)
  dump_be_registers();
#endif
}

// search within the queued BE elements to find the next BE element to process in display order
PMAEQ_T get_next_temporal_element(void)
{
  unsigned char chosen=FALSE;
  PMAEQ_T p,q;
  
  DPRINTF(MSG_FUNCTION, (TEXT("get_next_temporal_element Entry\n")));
  p = pmms->be_proc;
  
  // pass over anchor frames that have been displayed but are not yet discarded
  q=p;
  do {
    if (!q->sent_to_be) {
      p = q;
      chosen=TRUE;
    }
    q=q->next;
  } while ((q!=p) && !chosen);  
  
  if (!chosen) 
    return NULL;
  
  // now search the list for the next temporal frame
  for (q = pmms->be_proc->next; q != pmms->be_proc; q=q->next) 
  {
    if ((q->tnum < p->tnum) && (!q->sent_to_be))
      p = q;
  }
  return p;
}
   
unsigned char run_be_hw(void) 
{
  PMAEQ_T pmaeq;
  PRGBQ_T prgbq;
  
  DPRINTF(MSG_FUNCTION, (TEXT("run_be_hw entry\n")));
  DPRINTF(MSG_BE, (TEXT("run_be_hw() pmms->state 0x%x\n"),pmms->state));
  // if there is no source or destination then bail
  if (!pmms->be_proc) {
    pmms->state &= (~ENABLE_BE);
    DPRINTF(MSG_BE, (TEXT("run_be_hw: no source or destination !!!\n")));
    return FALSE;
  }
  if (!(pmaeq = get_next_temporal_element())) {
    pmms->state &= (~ENABLE_BE);
    DPRINTF(MSG_BE, (TEXT("run_be_hw: no temp el !!!\n")));
    return FALSE;
  }
  
#ifdef MAE_DUMP
  sprintf(pmms->pDumpPtr->szDumpStr[pmms->pDumpPtr->numEntries++], "run_be_hw: frame # %d\n",pmaeq->tnum);
#endif
  
  DPRINTF(MSG_BE, (TEXT("run_be_hw() pmms->state 0x%x\n"),pmms->state));
  
  if (!pmms->rgb_free) {
    DPRINTF(MSG_ERROR, (TEXT("run_be_hw: no rgb buffer ????\n")));
  }
  // attach a new rgb buffer
  DLCL_POP(RGBQ_T, &pmms->rgb_free, prgbq);
  pmaeq->rgb = prgbq->addr;  // assign the static rgb buffer associated with this rgbq
  pmaeq->sent_to_be = TRUE;  // tell the world this entry has made it to the be
  // UNNECESSARY??
  prgbq->ready_to_display = FALSE; // we are only beginning to fill the rgb buffer
  
  if(previous_pts > pmaeq->pts)
  {
    //DBGPRINT(WARNINGS,"run_be_hw(): current tnum %d, pts %d earlier than previous pts %d\n", 
    //     pmaeq->tnum, (int)pmaeq->pts, (int)previous_pts); // KK - avsync
  }
  
  previous_pts = prgbq->pts = pmaeq->pts;
  prgbq->dts = pmaeq->dts;
  prgbq->tnum = pmaeq->tnum;
  
  DLCL_APPEND(RGBQ_T, &pmms->rgb_write, prgbq);
  pmms->be_proc = pmaeq;  // move the ptr to the one we will now process
  
  // unnecessary
#if 0
  if (pmaeq->anchor_flag)
  {
    prgbq->start_time = 0;
  }
  else
  {
    prgbq->start_time = 1;
  }
#endif
  // PROGRAM THE BE REGISTERS
  program_be_regs(pmaeq, prgbq);
  
  DPRINTF(MSG_BE, (TEXT("PROGRAM BE:     %d pts %d\n"),pmaeq->tnum, prgbq->pts));
  return TRUE;
}

UINT32 init_rgbq_list(void) 
{
  UINT32 i=0;
  PRGBQ_T el;
  UINT32 queue_addr = KRNL_RGBQ;
  UINT32 rgb_buffer_addr = KRNL_RGB_FRAMES_BASE;
  
  // create free list
  while (i<NUM_RGBQ_ELEMENTS) 
  {
    el = (PRGBQ_T)queue_addr;
    el->addr = (PUINT32)rgb_buffer_addr;
    DLCL_APPEND(RGBQ_T, &pmms->rgb_free, el);
    queue_addr += sizeof(RGBQ_T);
    rgb_buffer_addr += SIZE_RGB_FRAME;
    i++;
  }
  return 0;
}

void program_lut(void) 
{
  unsigned long halut, valut;
  unsigned long hblut, vblut;
  unsigned long hclut, vclut;
  unsigned long val, i;
  
  halut = (unsigned long)MAEBE_SCFHALUT;
  valut = (unsigned long)MAEBE_SCFVALUT;
  hblut = (unsigned long)MAEBE_SCFHBLUT;
  vblut = (unsigned long)MAEBE_SCFVBLUT;
  hclut = (unsigned long)MAEBE_SCFHCLUT;
  vclut = (unsigned long)MAEBE_SCFVCLUT;
  
  for (i=0; i< LUTSIZE; i++) 
  {
    val = glut[i];
    //val = 0x00004000;   // PPKK - forced to passthrough 
    au_writel(val, (halut + i*4));
    au_writel(val, (valut + i*4));
    au_writel(val, (hblut + i*4));
    au_writel(val, (vblut + i*4));
    au_writel(val, (hclut + i*4));
    au_writel(val, (vclut + i*4));
  }
}

⌨️ 快捷键说明

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