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

📄 mae1200.cpp

📁 AU1200嵌入式处理器媒体加速引擎(mae)的驱动
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl ISDISPLAYED=%d fe=%s be=%s\n"),
             uiFramesDisplayed, RunStateStr(g_FEState), RunStateStr(g_BEState) ));
      *(DWORD *) pBufOut = uiFramesDisplayed;
    }
    break;
  case AU1XXXMAE_VIDEOROTATION:
    {
      DPRINTF(MSG_IOCTL, (TEXT("In AU1XXXMAE_VIDEOROTATION switch ")));
      set_video_rotation();
    }
    break;
  case AU1XXXMAE_FLUSH: /* flush and resync */
  case AU1XXXMAE_FLUSH_QUEUES: /* don't resync */
    DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH fe=%s be=%s bFlushing=%d FrameOut=%d\n"),
           RunStateStr(g_FEState), RunStateStr(g_BEState), g_bFlushing, g_FrameOutNum ));
    if (IsFEStopped() && IsBEStopped())
    {
      /* if were already stopped, then all has been flushed */
      DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH already stopped\n") ));
    }
    else
    {
      DWORD mask;
      unsigned int bResync=(dwCode==AU1XXXMAE_FLUSH);
      unsigned int SaveBEState=g_BEState;
      g_bFlushing = 1; /* flag that Flushing is busy */
      if (!IsFEStopped())
      {
        DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH stopping FE\n") ));
        change_FEstate(MAE_STATE_STOPPING);
      }
      if (IsRunning()) /* if we were running, pause first to give interrupt time to finish */
      {
        DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH pausing BE\n") ));
        change_BEstate(MAE_STATE_PAUSING);
        waitfor_BEstate(~MAE_STATE_PAUSING, 300);
      }
      else
      {
        /* wait for mae thread to transition to stopped */
        /* The interrupts will flush everything when they transition to STOPPED state. */
        waitfor_FEstate(~MAE_STATE_STOPPING, 300);
      }

      EnterCS(g_CriticalSection);
      DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH restoring states\n") ));
      mask = mask_interrupts(gbl_mask  | (1 << AU1200_LCD_INT));
      g_FrameOutNum = 0;  // note, change_BEstate will also reset on STOPPED
      
      /* recover BE & FE run states prior to Flushing */
      if (SaveBEState!=MAE_STATE_NONE && SaveBEState!=MAE_STATE_STOPPED)
        change_FEstate(MAE_STATE_STARTING);

      if (SaveBEState==MAE_STATE_PREROLL)
        change_BEstate(MAE_STATE_PREROLL);
      else if (SaveBEState==MAE_STATE_PAUSING || SaveBEState==MAE_STATE_PAUSED)
        change_BEstate(MAE_STATE_PAUSING); /* force BE to pick up next frame and pause again */
      else if (SaveBEState!=MAE_STATE_NONE && SaveBEState!=MAE_STATE_STOPPED)
        change_BEstate(SaveBEState);
      DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH done fe=%s be=%s\n"),
             RunStateStr(g_FEState), RunStateStr(g_BEState) ));
      g_bFlushing = 0;  /* Flushing done */
      unmask_interrupts(mask);
      LeaveCS(g_CriticalSection);
    }
    break;
  case AU1XXXMAE_ENDOFSTREAM:
    {
      /* this returns whether an EOS has been encountered (queues drained of all frames) */
      DWORD mask, bGotEOS=0;
      DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM fe=%s be=%s waitEOS=%d\n"),
             RunStateStr(g_FEState), RunStateStr(g_BEState), g_WaitForEOS ));

      EnterCS(g_CriticalSection);
      mask = mask_interrupts(gbl_mask  | (1 << AU1200_LCD_INT));      
      ResetEvent(g_hEndOfStreamSemaphore);
      g_WaitForEOS = 1;
      unmask_interrupts(mask);
      LeaveCS(g_CriticalSection);
      /* we check multiple times for EOS since it may be set when the rgb queue is starving */
      while (bGotEOS<4 && isBEstate(MAE_STATE_PREROLL|MAE_STATE_STARTING|MAE_STATE_PLAYING))
      {
        DWORD dwReturn;
        DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM check: fe=%s be=%s\n"),
             RunStateStr(g_FEState), RunStateStr(g_BEState) ));
        dwReturn = WaitForSingleObject(g_hEndOfStreamSemaphore,300);
        if(dwReturn == WAIT_OBJECT_0)
        {
          bGotEOS++;
          g_WaitForEOS = 1;
        }
        else
        {
          DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM timeout\n")));
          HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,TEXT("PowerManager/ActivityTimer/UserActivity"));
          SetEvent(hEvent);
          CloseHandle(hEvent);
        }
        if (!pmms->be_proc && !pmms->fe_proc) /* all queues are empty */
        {
          DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM queues empty\n")));
          break;
        }
      }
      g_WaitForEOS = 0;
      *(DWORD *) pBufOut = bGotEOS;
      DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM done: GotEOS=%d fe=%s be=%s\n"),
             bGotEOS, RunStateStr(g_FEState), RunStateStr(g_BEState) ));
    }
    break;
  case AU1XXXMAE_GETCURRENTSTATE:
    {
      DPRINTF(MSG_IOCTL, (TEXT("MAE_Ioctl GETCURRENTSTATE fe=%s be=%s\n"),
             RunStateStr(g_FEState), RunStateStr(g_BEState) ));
      *(DWORD *) pBufOut = (DWORD)g_FEState;
    }
    break;

#ifdef YUV_DUMPS
  case AU1XXXMAE_GETINTERRUPTSTATE:
    {
      // The decoder(s) will wait until it receives a FE_DONE
      // indication before starting to dump out the YUV data
      DPRINTF(MSG_IOCTL, (TEXT("MAE_Ioctl GETINTERRUPTSTATE")));
      *(DWORD *) pBufOut = (DWORD)nFrameState;

      // Clear the flag now to make sure that we indicate 
      // FE_DONE iff we received an interrupt
      if (nFrameState == INT_STATE_FE_DONE)
        nFrameState = INT_STATE_NONE;
    }
    break;
#endif

  case AU1XXXMAE_GETDIVXSTR:
    {
      PDIVX_DRM_STRUCT  pDivX_drm=(DIVX_DRM_STRUCT *)pBufOut;
      unsigned int  salt[8] = { 0x9defc909, 0x301ec998, 0xcde43ceb, 0x66dd8015, 
                                0xf5086c66, 0x268d0a3a, 0x89af5557, 0xd19c7d87};  

      pDivX_drm->reg30   = au_readl(0xB4012030) ^ salt[0];
      pDivX_drm->reg34   = au_readl(0xB4012034) ^ salt[1];
      pDivX_drm->reg60   = au_readl(0xB4012060) ^ salt[2];
      pDivX_drm->prid    = (DWORD)getPRId()     ^ salt[3];
      pDivX_drm->config1 = (DWORD)getconfig1()  ^ salt[4];
      pDivX_drm->reg1000 = au_readl(0xB4013000) ^ salt[5];
      pDivX_drm->reg100c = au_readl(0xB401300C) ^ salt[6];
      pDivX_drm->reg101c = au_readl(0xB4013010) ^ salt[7];
    }
    break;

  case AU1XXXMAE_GETPRID:
    {
      DPRINTF(MSG_IOCTL, (TEXT("MAE_Ioctl GETPRID\n")));
      *(DWORD *) pBufOut = (DWORD)getPRId();
    }
    break;
  default :
    RetVal = FALSE;
    break;
  }
  DPRINTF (MSG_IOCTL, (TEXT("-MAE_IOControl %s \r\n"), (RetVal == TRUE) ? TEXT("Success") : TEXT("Error")));
  return(RetVal);
}


// Allocate physical contigous memory for the MAE device
// Memory is now allocated from a region reserved in the config.bib file
BOOL AllocateDeviceMemory(void) 
{
  BOOL bRet = 0;
  PVOID BaseAddress;
  
#ifdef YUV_DUMPS
  UINT32 size = SIZE_MAE_MASTER_STRUCT + SIZE_AVSYNC + SIZE_MAEQ + SIZE_DATAQ + SIZE_YUVQ + SIZE_RGBQ 
        + SIZE_DESCRIPTOR_BASE + SIZE_DATA_BUFFER_BASE + SIZE_RGB_FRAMES_BASE
        + SIZE_YUV_FRAMES_BASE + SIZE_SCRATCH_PAD_BASE;
  
  nTotalAllocatedSize = size;
#else
  UINT32 size = SIZE_MAE_MASTER_STRUCT + SIZE_AVSYNC + SIZE_MAEQ + SIZE_DATAQ + SIZE_YUVQ + SIZE_RGBQ 
        + SIZE_DESCRIPTOR_BASE + SIZE_DATA_BUFFER_BASE;
  
  nTotalAllocatedSize = size;
#endif
  
  DPRINTF(MSG_MEMORY, (TEXT("AllocateDeviceMemory: master struct size: 0x%x (%d bytes)\n"), sizeof(MAE_MASTER_T), sizeof(MAE_MASTER_T)));
  DPRINTF(MSG_MEMORY, (TEXT("AllocateDeviceMemory: mem to be allocated: 0x%x (%d bytes)"), size, size));
  
  // This value comes from our config.bib file
  gMaePhysBaseAddress = 0x00100000;
  
  // Only large data buffers should be cacheable.
  //
  unsigned long noCacheSize = SIZE_MAE_MASTER_STRUCT +  
    SIZE_DESCRIPTOR_BASE; // + SIZE_RGBQ + SIZE_YUVQ + SIZE_DATAQ + SIZE_MAEQ + SIZE_AVSYNC;
  
  size -= noCacheSize;
  
  // Align to page (4K) boundary
  //
  noCacheSize = (noCacheSize + 4095) & ~4095;
  size = (size + 4095) & ~4095;
  
  BaseAddress = VirtualAlloc(0, size + noCacheSize, MEM_RESERVE, PAGE_NOACCESS);
  
  //bRet = VirtualCopy(BaseAddress, (PVOID)(gMaePhysBaseAddress | 0x80000000), size, PAGE_READWRITE | PAGE_NOCACHE);
  
  // Map non-cacheable area
  //
  bRet = VirtualCopy(BaseAddress, (PVOID)((gMaePhysBaseAddress) >> 8), noCacheSize, PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE);
  
  if (!bRet)
  {
    RPRINTF(MSG_ERROR,(TEXT("Failed mapping non-cacheable space!!!\n")));
  }
  
  // This turns on caching.
  bRet = VirtualCopy((PVOID)((ULONG)BaseAddress + noCacheSize), (PVOID)((gMaePhysBaseAddress + noCacheSize) >> 8), size, PAGE_PHYSICAL | PAGE_READWRITE);
  
  if (!bRet)
  {
    RPRINTF(MSG_ERROR,(TEXT("Failed mapping cacheable space!!!\n")));
    VirtualFree(BaseAddress, 0, MEM_RELEASE);
    return FALSE;
  }
  
  gVirtualBaseAddress = (unsigned long)BaseAddress;
  
  KRNL_MAE_MASTER_STRUCT  = gVirtualBaseAddress;
  KRNL_DESCRIPTOR_BASE = KRNL_MAE_MASTER_STRUCT + SIZE_MAE_MASTER_STRUCT;
    
  KRNL_RGBQ = gVirtualBaseAddress + noCacheSize;
  KRNL_YUVQ = KRNL_RGBQ + SIZE_RGBQ;
  KRNL_DATAQ = KRNL_YUVQ + SIZE_YUVQ;
  KRNL_MAEQ = KRNL_DATAQ + SIZE_DATAQ;
  KRNL_AVSYNC = KRNL_MAEQ + SIZE_MAEQ;
  KRNL_DATA_BUFFER_BASE = KRNL_AVSYNC + SIZE_AVSYNC;
  
  KRNL_RGB_FRAMES_BASE = KRNL_DATA_BUFFER_BASE + SIZE_DATA_BUFFER_BASE;
  KRNL_YUV_FRAMES_BASE = KRNL_RGB_FRAMES_BASE + SIZE_RGB_FRAMES_BASE;
  KRNL_SCRATCH_PAD_BASE = KRNL_YUV_FRAMES_BASE + SIZE_YUV_FRAMES_BASE;
  
  DPRINTF (MSG_MEMORY, (TEXT("Non Cacheable Base = 0x%X\n"), gVirtualBaseAddress));
  DPRINTF (MSG_MEMORY, (TEXT("Cacheable Base     = 0x%X\n"), gVirtualBaseAddress + noCacheSize));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_MAE_MASTER_STRUCT = 0x%X\n"), KRNL_MAE_MASTER_STRUCT));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_DESCRIPTOR_BASE   = 0x%X\n"), KRNL_DESCRIPTOR_BASE));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_RGBQ              = 0x%X\n"), KRNL_RGBQ));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_YUVQ              = 0x%X\n"), KRNL_YUVQ));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_DATAQ             = 0x%X\n"), KRNL_DATAQ));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_MAEQ              = 0x%X\n"), KRNL_MAEQ));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_AVSYNC            = 0x%X\n"), KRNL_AVSYNC));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_DATA_BUFFER_BASE  = 0x%X\n"), KRNL_DATA_BUFFER_BASE));

  DPRINTF (MSG_MEMORY, (TEXT("\n")));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_RGB_FRAMES_BASE  = 0x%X, size 0x%X\n"), 
                                KRNL_RGB_FRAMES_BASE, SIZE_RGB_FRAMES_BASE));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_YUV_FRAMES_BASE  = 0x%X, size 0x%X\n"), 
                                KRNL_YUV_FRAMES_BASE, SIZE_YUV_FRAMES_BASE));
  DPRINTF (MSG_MEMORY, (TEXT("KRNL_SCRATCH_PAD_BASE  = 0x%X, size 0x%X\n"), 
                                KRNL_SCRATCH_PAD_BASE, SIZE_SCRATCH_PAD_BASE));

  
  // establish the debug pointer structure. This is squeezed in the 4k page
  //  used by avsync....
  pdbgout = (PDBGOUT)KRNL_AVSYNC;
  return TRUE;
}

void ReadRegistryKeys(void)
{
  HKEY        hKey;
  ULONG BytesReturned;
  
  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("Drivers\\BuiltIn\\MAE1200"),0,0,&hKey) == ERROR_SUCCESS) {
    RegQueryValueEx(hKey,TEXT("IgnorePTS"),0,NULL,(PUCHAR)&g_RegistryIgnorePTS,&BytesReturned);
    RegCloseKey(hKey);
  }
  DPRINTF (MSG_INIT, (TEXT("ReadRegistryKeys end IgnorePTS:%d\n"),g_RegistryIgnorePTS));
}

void ShowVersion(void)
{
  TCHAR     szTemp[1024];
  wsprintf (szTemp,TEXT("Maedriver, v%d.%d.%d.%d\n"), kVersion_Main,kVersion_Sub,kVersion_Build,kVersion_BuildSub);
  OutputDebugString(szTemp);
}

void mae_wake_up_function(void)
{
  UINT32 fe_armed = FALSE;
  UINT32 be_armed = FALSE;
  
  DPRINTF (MSG_FUNCTION, (TEXT("mae_wake_up_function\n")));
  if(pmms->StillSleeping)
  {
    DPRINTF (MSG_STATE, (TEXT("mae_wake_up_function() StillSleeping\n")));
    if(pmms->yuv_free && pmms->rgb_free)
    {
      if (pmms->state & ENABLE_FE) {
        // not the last frame, re-arm the front end
        my_fe_armed=fe_armed = run_fe_hw();
#ifdef DUMP_FE
        DPRINTF(MSG_TIME, (TEXT("@wake_up@\n")));
        dump_fe();
#endif
        // note: if run_fe_hw returns false, 
        // cannot rearm the fe even though the system has it enabled. To keep the
        // pipeline intact we freeze the be because the fe cannot feed it. With the
        // be left on it could consume the forward anchor before it should be.
      }     
      // The next temporal buffer is chosen and enabled for processing
      if ((pmms->state & ENABLE_BE) && !(pmms->state & MAE_FREEZE)) {
        my_be_armed=be_armed = run_be_hw();
      }    
      pmms->StillSleeping = 0;      
      // really start the FE and BE, arm interrupts
      kickstart_hw(fe_armed, be_armed);
    }
  }
}

UINT32 clear_rgbq_planes(void) 
{
  UINT32 rgb_buffer_addr = KRNL_RGB_FRAMES_BASE;
    
  DPRINTF (MSG_FUNCTION, (TEXT("clear_rgbq_planes entry:\n")));
  memset((PVOID)rgb_buffer_addr, 0, SIZE_RGB_FRAME*NUM_RGBQ_ELEMENTS);
  return 0;
}

//
// Queue element processing routines
//
void clean_maeq(PMAEQ_T el) 
{
  if (!el) return;
  
  el->anchor_flag = 0;
  el->sent_to_be = 0;
  el->state_change = 0;
  el->endframe_flag = 0;
  el->update_mode_flag = 0;
  el->interlacing_on = 0;
  el->interlaced_frame_done = 1;
  el->topfield_length = 0;
  el->stream_type = 0;
  el->dummysubmit = 0;
  el->prog_frame = 1;
  el->nFlushMAE = 0;
}

// assumes that interrupts have been disabled and that mae is not currently running
UINT32 init_maeq_list(UINT32 num) 
{
  UINT32 i=0;
  UINT32 size;
  PMAEQ_T el;
  char sstr[256]="";
  UINT32 addr = KRNL_MAEQ;
  
  DPRINTF(MSG_FUNCTION, (TEXT("init_maeq_list entry\n")));
  
  // limit the number of elements to what is supported
  if (num > MAX_NUM_MAEQ_ELEMENTS)
    num = MAX_NUM_MAEQ_ELEMENTS;
    
  // create free list
  size = sizeof(MAEQ_T);
  
  DPRINTF(MSG_MEMORY, (TEXT("init_maeq_list creating %d maeq elements of size %d bytes each\n"), num, size));
  
  while (i<num) {
    el = (PMAEQ_T)addr;
    DLCL_APPEND(MAEQ_T, &pmms->maeq_free, el);
    addr += size;
    i++;
  }
  
  return 0;
}

void init_desc_ring(void)
{
  pmms->pDescRingStart = pmms->pCurDescPtr = (PUINT32) KRNL_DESCRIPTOR_BASE; //allocate_descriptor_memory(DEFAULT_DESCRIPTORS_SIZE, LOCK_MEM);
  pmms->pDescRingEnd = (PUINT32)((char *)(pmms->pDescRingStart) + SIZE_DESCRIPTOR_BASE); 
  // We need at least one empty descriptor after each valid descriptor. In case of interlaced mode, we will an additional descriptor
  pmms->pDescRingEnd--;
  pmms->pDescRingEnd--;
  pmms->pDescRingEnd--;
  pmms->pDescRingEnd--;
  DPRINTF(MSG_MEMORY, (TEXT("

⌨️ 快捷键说明

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