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

📄 mae_fe.c

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


YUV_TABLE gYUVTable[NUM_YUVQ_ELEMENTS] = 
{
  {0, "B0"},
  {0, "B1"},
  {0, "B2"},
  {0, "B3"} 
};
  
EXTERN reg_data RegData[] = 
{ 
  {0,    "Config Reg"},
  {0x4,  "cur Y ptr"},
  {0x8,  "fwd Y ref"},
  {0xc,  "bwd Y ref"} ,
  {0x10, "cur Cb ptr"},
  {0x14, "fwd Cb ref"},
  {0x18, "bwd Cb ref"},
  {0x1c, "cur Cr Ptr"},
  {0x20, "fwd Cr ref"},
  {0x24, "bwd Cr ref"},
  {0x28, "picture size"},
  {0x2c, "intensity comp"},
  {0x38, "fwd Y bot"},
  {0x3c, "fwd Cb bot"} ,
  {0x40, "fwd Cr bot"},
  {0x44, "bwd Y bot"},
  {0x48, "bwd Cb bot"},
  {0x4c, "bwd Cr bot"},
  {0x5c, "WMV9 pquant"} 
};

DWORD g_WaitForEOS = 0;
  
void program_fe_regs(PMAEQ_T pmaeq, UINT32 ulInterlaced)
{
  UINT32 i = 0;
  UINT32 val, regmask;
  reg_info *preg_values;
  
#ifdef REG_DEBUG
  // KK - rev2
  UINT32 val2;
  reg_info *preg_values2;
  // ~KK - rev2
#endif
  
  if(ulInterlaced)
  {
    preg_values = (reg_info *)(&pmaeq->fe_reglist_field);
#ifdef REG_DEBUG
    preg_values2 = (reg_info *)(&pmaeq->mae_fe_reglist_field);  // KK - rev2
#endif
  }
  else
  {
    preg_values = (reg_info *)(&pmaeq->fe_reglist);
#ifdef REG_DEBUG
    preg_values2 = (reg_info *)(&pmaeq->mae_fe_reglist); // KK - rev2
#endif
  }
  
#ifdef REG_DEBUG
  regmask = preg_values2->regmask;
#else
  regmask = preg_values->regmask;
#endif
  
  while (regmask)
  {
    if(regmask & 1) 
    {
      val = *((PUINT32)preg_values+i);
#ifdef REG_DEBUG
      val2 = *((PUINT32)preg_values2+i);
      if(val != val2)
        DPRINTF(MSG_FE, (TEXT("MISMATCH: reg offset %x org val %x MAE comp val %x\n"),RegData[i].offset, val, val2));
      au_writel(val, ((UINT32)MAEFE_BASE + RegData[i].offset));
#else
      au_writel(val, ((UINT32)MAEFE_BASE + RegData[i].offset));
#endif
      DPRINTF(MSG_FE, (TEXT("Reg offset 0x%x  Value 0x%x\n"),RegData[i].offset, val));
    }
    regmask = (regmask >> 1);
    i++;
  } 
  
  // Program the Scratch pad for WMV9 filter processing (Can be done only per run)
  au_writel(MAE_PADDR(KRNL_SCRATCH_PAD_BASE), ((UINT32)MAEFE_SCRATCHPAD));
  au_writel(MAE_PADDR(pmaeq->descriptors),((UINT32)MAEFE_DMADSCR1));
}

unsigned char update_anchor_frames(void) 
{
  PMAEQ_T pmaeq;
  PYUVQ_T pyuvq;
#ifdef MAE_DBG
  int i;
#endif
  
  DPRINTF(MSG_FUNCTION, (TEXT("update_anchor_frames(): entry!!!\n")));
  
  if (!(pmms->fe_proc)) {
    DPRINTF(MSG_ERROR, (TEXT("update_anchor_frames(): no FE entry!!!\n")));
    return 0;
  }
  // here we take the newly programmed FE queue entry and adjust the anchor
  // frame pointers if needed.
  
  // first check to see if this is an anchor frame, else we're done
  if (!(pmms->fe_proc->anchor_flag)){
    DPRINTF(MSG_INFO, (TEXT("update_anchor_frames(): no pmms->fe_proc->anchor_flag returning!!!\n")));
    return 1;
  }
  
  // there are anchors
  if (pmms->b_anchor) 
  {
    pmms->b_anchor->anchor_flag = 0;  // de-anchor the old one
    // if already displayed then free it too
    if (pmms->b_anchor->sent_to_be) 
    {
      // for the case where the back anchor is the current be entry
      if (pmms->be_proc == pmms->b_anchor) 
      {
        // free the yuv buffer
        pyuvq = (PYUVQ_T)pmms->be_proc->pyuvq;
        
#ifdef MAE_DBG
        //DPRINTF(MSG_BE, (TEXT("update_anchor_frames - 1: Freeing YUV buffer  \n")));
        for(i=0; i<NUM_YUVQ_ELEMENTS; i++)
        {
          if (gYUVTable[i].pyuvq == pyuvq)
          {
            //DPRINTF(MSG_BE, (TEXT("%s\n"),gYUVTable[i].szBufName));
            break;
          }
        }
#endif
        
        DLCL_REMOVE(YUVQ_T, &pmms->yuv_inuse, pyuvq);
        
        DLCL_APPEND(YUVQ_T, &pmms->yuv_free, pyuvq);
        // MK
        if(pmms->nFramesInSystem > 0)
          pmms->nFramesInSystem--;
        // free the element
        DLCL_POP(MAEQ_T, &pmms->be_proc, pmaeq);
        if(!pmaeq)
        {
          DPRINTF(MSG_ERROR, (TEXT("update_anchor_frames()-2: MAEQ null\n")));
          return 0;
        }
        
#ifdef MAE_DUMP
        sprintf(pmms->pDumpPtr->szDumpStr[pmms->pDumpPtr->numEntries++], "update_anchor: freeing b_anchor # %d\n",pmaeq->tnum);
#endif
        
        DLCL_APPEND(MAEQ_T, &pmms->maeq_free, pmaeq);
        pmms->b_anchor = NULL; // init the anchor
      }
      // and for the case where the back anchor is just one entry in the list
      else 
      {
        // free the yuv buffer
        pyuvq = (PYUVQ_T)pmms->b_anchor->pyuvq;
        
#ifdef MAE_DBG
        DPRINTF(MSG_BE, (TEXT("update_anchor_frames - 2: Freeing YUV buffer  \n")));
        for(i=0; i<NUM_YUVQ_ELEMENTS; i++)
        {
          if (gYUVTable[i].pyuvq == pyuvq)
          {
            DPRINTF(MSG_BE, (TEXT("%s\n"),gYUVTable[i].szBufName));
            break;
          }
        }
#endif
        
        DLCL_REMOVE(YUVQ_T, &pmms->yuv_inuse, pyuvq);
        
        DLCL_APPEND(YUVQ_T, &pmms->yuv_free, pyuvq);
        // free the element
        DLCL_POP(MAEQ_T, &pmms->b_anchor, pmaeq);
        if(!pmaeq)
        {
          DPRINTF(MSG_ERROR, (TEXT("update_anchor_frames()-4: MAEQ null\n")));
          return 0;
        }

        // KK - We just pulled the b_anchor frame. Make sure we also pull it out of the be_proc queue.
        DLCL_REMOVE(MAEQ_T, &pmms->be_proc, pmaeq);
        
#ifdef MAE_DUMP
        sprintf(pmms->pDumpPtr->szDumpStr[pmms->pDumpPtr->numEntries++], "update_anchor: freeing f_anchor # %d\n",pmaeq->tnum);
#endif
        DLCL_APPEND(MAEQ_T, &pmms->maeq_free, pmaeq);
        pmms->b_anchor = NULL; // init the anchor
      }
    }   
  }
  // else if there is only an fanchor
  if (pmms->f_anchor) 
    pmms->b_anchor = pmms->f_anchor;  // slide the anchors
  // assign the front anchor
  pmms->f_anchor = pmms->fe_proc;
  DPRINTF(MSG_FUNCTION, (TEXT("update_anchor_frames(): exit pmms->maeq_free %x!!!\n"),pmms->maeq_free));
  return 1;
}

unsigned long get_yuvbufferaddr(unsigned long nYUVIndex)
{
  unsigned long addr;
  
  if(nYUVIndex >= 3)
    return 0;
  
  addr = pmms->yuv_region_offset +(nYUVIndex * SIZE_YUV_FRAME);
  addr = (UINT32)(addr + (UINT32)gMaePhysBaseAddress);
  //DPRINTF (MSG_BUFFER, (TEXT("get_yuvbufferaddr: addr  %x, nYUVIndex %d\n"),addr,nYUVIndex ));
  
  return (addr);
}

unsigned char run_fe_hw(void) 
{
  PMAEQ_T pmaeq;
  PYUVQ_T pyuvq;
  
  DPRINTF(MSG_FE|MSG_TIME, (TEXT("run_fe_hw: Entry: pmms->state 0x%x\n"),pmms->state));
  // this state is caught when the app forces a hw start
  // check to renable if MAE was frozen
  if (pmms->state & MAE_FREEZE) {
    pmms->state &= ~(MAE_FREEZE);
  }
  
  // this state is caught during an interrupt
  // if there is no source or no destination buffer then bail
  if (!(pmms->fe_wait)) {
    // freeze the pipeline!!!
    if(!g_WaitForEOS)
    {
      pmms->state |= MAE_FREEZE;
    }
    else
    {
      pmms->state &= (~ENABLE_FE);
    }
    return FALSE;
  }
  
  // arm the front end
  DLCL_POP(MAEQ_T, &pmms->fe_wait, pmaeq);
  DPRINTF(MSG_FE|MSG_TIME, (TEXT("pmms->fe_wait: %x\n"), pmms->fe_wait));

  // KK - This is a dummy submission that has made it up to here. Freeing it up here.
  if(!pmaeq->stream_type)
  {
    DLCL_REMOVE(DATAQ_T, &pmms->data_inuse, pmaeq->pdataq);  
    DLCL_APPEND(DATAQ_T, &pmms->data_free, pmaeq->pdataq);

    DLCL_APPEND(MAEQ_T, &pmms->maeq_free, pmaeq);
    return FALSE;
  }
  
#ifdef NEW_YUV
  DLCL_POP(YUVQ_T, &pmms->yuv_free, pyuvq);
  if (!pyuvq) {
    DPRINTF(MSG_FE, (TEXT("new_yuvbuffer: No free YUV buffer available !!!\n")));
    return FALSE;
  }
  DLCL_APPEND(YUVQ_T, &pmms->yuv_inuse, pyuvq);
  
  pmaeq->y = pyuvq->addr;
  pmaeq->u = (PUINT32)((UINT32)pmaeq->y + (pmaeq->encoded_picture_height*pmaeq->encoded_picture_linesize));
  pmaeq->v = (PUINT32)((UINT32)pmaeq->u + (pmaeq->encoded_picture_height*pmaeq->encoded_picture_linesize)/4);
  pmaeq->pyuvq = pyuvq;
#endif
  
  DLCL_APPEND(MAEQ_T, &pmms->fe_proc, pmaeq);
  pmms->state |= ENABLE_FE;
  
  // tell the state machine this is the last frame
  if (pmaeq->endframe_flag)
    pmaeq->state_change |= DISABLE_FE;
  
#ifdef MAE_DUMP
  sprintf(pmms->pDumpPtr->szDumpStr[pmms->pDumpPtr->numEntries++], "run_fe_hw: frame # %d\n",pmaeq->tnum);
#endif
  
  update_anchor_frames();
  
  // Now compute the reference pointers and config parameters for the frame.
  compute_reg_values(pmaeq, 0,(pmaeq->picture_structure == BOTTOM_FIELD)?1:0);
  
  // PROGRAM THE FRONT END REGISTERS
  program_fe_regs(pmaeq, 0);
  
  DPRINTF(MSG_FE, (TEXT("run_fe_hw: Exit \n")));
  
  return TRUE;  
}

void ring_fe_doorbell(void) 
{
  unsigned long rval;
  rval = au_readl(MAEFE_DMADBELL);
  //DPRINTF(MSG_FE, (TEXT("ring_fe_doorbell: rval %x\n"), rval));
  au_writel(MAEFE_DMADBELL_DB, MAEFE_DMADBELL);
  rval = 1;
}

unsigned char discard_fe(void)
{
  PMAEQ_T pmaeq;
  PYUVQ_T pyuvq;
  
  //DPRINTF(MSG_FUNCTION, (TEXT("discard_fe() entry\n")));
  // if there is no source to discard then bail
  if (!(pmms->fe_proc)) {
    return FALSE;
  }
  
  // move the FE element to be the BE queue
  DLCL_POP(MAEQ_T, &pmms->fe_proc, pmaeq);
  
  // free the yuv buffer
  if (pmms->yuv_inuse) 
  {  
    DLCL_POP(YUVQ_T, &pmms->yuv_inuse, pyuvq);
    pyuvq->addr = pmaeq->y;
    //DPRINTF(MSG_FE, (TEXT("YUV addr: 0x%x\n"),(UINT32)(pyuvq->addr)));
    DLCL_APPEND(YUVQ_T, &pmms->yuv_free, pyuvq);
  }
  
  DLCL_APPEND(MAEQ_T, &pmms->maeq_free, pmaeq);
  return TRUE;
}

UINT32 init_yuvq_list(void) 
{
  UINT32 i=0;
  PYUVQ_T el;
  UINT32 queue_addr = KRNL_YUVQ;
  UINT32 yuv_buffer_addr = KRNL_YUV_FRAMES_BASE;
  
  //DPRINTF(MSG_FUNCTION, (TEXT("init_yuvq_list entry\n")));
  pmms->yuv_region_offset = yuv_buffer_addr - (UINT32)pmms;
  
  // create free list
  while (i<NUM_YUVQ_ELEMENTS) 
  {
    el = (PYUVQ_T)queue_addr;
    el->addr = (PUINT32)yuv_buffer_addr;
    gYUVTable[i].pyuvq = el;
    DPRINTF(MSG_INIT, (TEXT("init_yuvq_list YUV buffer %d address: %x\n"),(i+1),(UINT32)el->addr));
    DLCL_APPEND(YUVQ_T, &pmms->yuv_free, el);
    queue_addr += sizeof(YUVQ_T);
    yuv_buffer_addr += SIZE_YUV_FRAME;
    i++;
  }
  
  return 0;
}

void release_buffer_memory(PMAEQ_T el) 
{
  // move the consumption ptr to the end of this allocated block
  pmms->inuse_bufferbase = (PUINT32)((UINT32)el->buffer + (UINT32)DEFAULT_BUFSIZE);
}

#ifndef MAE_HW
PUINT32 release_extra_info_memory(PMAEQ_T el)
{
  // move the consumption ptr to the end of this allocated block
  pmms->extra_info_inuse_base = el->extra_info + el->extra_info_size;
  return 0;
}
#endif

⌨️ 快捷键说明

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