📄 enchw.c
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2005 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Project : 1200s
--
-- Abstract : Module for encoder HW registers access
--
-------------------------------------------------------------------------------*/
//------------------------------------------------------------------------------
//
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
Table of context
1. Include headers
2. Module defines
3. Local function prototypes
4. Functions
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include <windows.h>
#include <pkfuncs.h>
#include <ceddk.h>
#include <csp.h>
#include "enchw.h"
/*------------------------------------------------------------------------------
2. Module defines
------------------------------------------------------------------------------*/
#define ENCHW_HWID_REG 0x88
#define ENCHW_HWID_MASK 0xFFFF0000
#define ENCHW_HWID_VAL 0x52510000
#define ENCHW_REGMAP_SIZE 35*4
#define ENCHW_REGMAP_PADDR CSP_BASE_REG_PA_MPEG4_ENCODER
#define ENCHW_REG32(eh,o) (*(volatile unsigned long*)((eh)->RegBase + (o)))
#define ENCHW_WRITE_REG32(eh,o,v) do { ENCHW_REG32(eh,o) = (v); } while (0)
#define ENCHW_READ_REG32(eh,o ) ENCHW_REG32(eh,o)
#define ENCHW_MUTEX _T("ENCHW_MUTEX")
/*------------------------------------------------------------------------------
3. Local function prototypes
------------------------------------------------------------------------------*/
static int EnableEncoderHw(void);
static void DisableEncoderHw(void);
static __inline u32 EnableRegAccess ( EncHw_t* enchw, u32 offset );
static __inline void RestoreRegAccess( EncHw_t* enchw, u32 clearmask );
/*------------------------------------------------------------------------------
4. Functions
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
EncHw_Init
------------------------------------------------------------------------------*/
EncHw_t* EncHw_Init(void)
{
EncHw_t* enchw;
PHYSICAL_ADDRESS phyAddr;
u32 hwId;
int status;
// 1. Allocate EncHw instance
enchw = (EncHw_t*)malloc( sizeof(EncHw_t) );
if( enchw==NULL )
{
return NULL;
}
// Reset enchw instance values
enchw->RegBase = NULL;
enchw->RegSize = 0;
enchw->Mutex = NULL;
// 2. Enable power and clocks for encoder HW
status = EnableEncoderHw();
if( status )
{
EncHw_Release( enchw );
return NULL;
}
// 3. Map HW registers to user sape
phyAddr.QuadPart = ENCHW_REGMAP_PADDR;
enchw->RegBase = MmMapIoSpace( phyAddr, ENCHW_REGMAP_SIZE, FALSE );
if( enchw->RegBase == NULL )
{
EncHw_Release( enchw );
return NULL;
}
enchw->RegSize = ENCHW_REGMAP_SIZE;
// 4. Check for correct encoder by reading HW ID
hwId = EncHw_ReadReg( enchw, ENCHW_HWID_REG );
if( (hwId&ENCHW_HWID_MASK) != ENCHW_HWID_VAL )
{
EncHw_Release( enchw );
return NULL;
}
// 5. Create mutex
enchw->Mutex = CreateMutex( NULL, FALSE, ENCHW_MUTEX );
if( enchw->Mutex==NULL )
{
EncHw_Release( enchw );
return NULL;
}
return enchw;
}
/*------------------------------------------------------------------------------
EncHw_Release
------------------------------------------------------------------------------*/
void EncHw_Release( EncHw_t* enchw )
{
ASSERT( enchw!=NULL );
// 5. Delete mutex
if( enchw->Mutex != NULL )
{
CloseHandle( enchw->Mutex );
enchw->Mutex = NULL;
}
// 4. Nothing to be done for HW ID check!
// 3. Release HW registers mapping
if( enchw->RegBase != NULL )
{
MmUnmapIoSpace( enchw->RegBase, enchw->RegSize );
enchw->RegBase = NULL;
enchw->RegSize = 0;
}
// 2. Disable power/clocks for encoder HW
DisableEncoderHw();
// 1. Free encoder HW instance
free( enchw );
}
/*------------------------------------------------------------------------------
EncHw_Reset
------------------------------------------------------------------------------*/
void EncHw_Reset( EncHw_t* enchw )
{
u32 reg;
ASSERT( enchw!=NULL );
// Clear all regs but read-only HwId. HCLK enabled by WriteReg.
for( reg=0 ; reg < ENCHW_REGMAP_SIZE-4 ; reg += 4 )
EncHw_WriteReg( enchw, reg, 0 );
}
/*------------------------------------------------------------------------------
EncHw_WriteReg
------------------------------------------------------------------------------*/
void EncHw_WriteReg( EncHw_t* enchw, u32 offset, u32 val )
{
u32 saved;
ASSERT( enchw!=NULL && offset<=enchw->RegSize );
saved = EnableRegAccess( enchw, offset );
ENCHW_WRITE_REG32( enchw, offset, val );
RestoreRegAccess( enchw, saved );
}
/*------------------------------------------------------------------------------
EncHw_ReadReg
------------------------------------------------------------------------------*/
u32 EncHw_ReadReg( EncHw_t* enchw, u32 offset )
{
u32 val, saved;
ASSERT( enchw!=NULL && offset<=enchw->RegSize );
saved = EnableRegAccess( enchw, offset );
val = ENCHW_READ_REG32( enchw, offset );
RestoreRegAccess( enchw, saved );
return val;
}
/*------------------------------------------------------------------------------
IIM mapping
------------------------------------------------------------------------------*/
#define IIM_BASE CSP_BASE_REG_PA_IIM
#define IIM_SIZE 0x1800
#define IIM_REG32(o) (*(volatile unsigned long*)(iimBase + (o)))
#define IIM_WRITE_REG32(o,v) do { IIM_REG32(o) = (v); } while (0)
#define IIM_READ_REG32(o ) IIM_REG32(o)
/*------------------------------------------------------------------------------
EnableEncoderHw
------------------------------------------------------------------------------*/
i32 EnableEncoderHw( void )
{
PHYSICAL_ADDRESS phyAddr;
PUCHAR iimBase;
DDKClockSetGatingMode(DDK_CLOCK_GATE_INDEX_IIM,
DDK_CLOCK_GATE_MODE_ENABLED_ALL);
// Map IIM registers
phyAddr.QuadPart = IIM_BASE;
iimBase = MmMapIoSpace( phyAddr, IIM_SIZE, FALSE );
if( iimBase == NULL )
{
return -1;
}
// Override fuse for Hantro HW clock
if( IIM_READ_REG32(0x808) & 0x04 && !(IIM_READ_REG32(0x800) & 1<<5)
)
{
IIM_WRITE_REG32( 0x808, IIM_READ_REG32(0x808) & 0xfffffffb );
}
// Unmap IIM
MmUnmapIoSpace( iimBase, IIM_SIZE );
DDKClockSetGatingMode(DDK_CLOCK_GATE_INDEX_IIM,
DDK_CLOCK_GATE_MODE_DISABLED);
// Save current settings and enable encoder HW clock
DDKClockSetGatingMode( DDK_CLOCK_GATE_INDEX_MPEG4, DDK_CLOCK_GATE_MODE_ENABLED_ALL );
return 0;
}
/*------------------------------------------------------------------------------
DisableEncoderHw
------------------------------------------------------------------------------*/
void DisableEncoderHw(void)
{
DDKClockSetGatingMode( DDK_CLOCK_GATE_INDEX_MPEG4, DDK_CLOCK_GATE_MODE_DISABLED );
}
/*------------------------------------------------------------------------------
EnagleRegAccess
------------------------------------------------------------------------------*/
static __inline u32 EnableRegAccess( EncHw_t* enchw, u32 offset )
{
#define IPS 0
#define HCLK 1
static const u32 clockSource[] =
{
/*0x00*/ IPS, /*0x04*/ IPS, /*0x08*/ IPS, /*0x0C*/ IPS,
/*0x10*/ HCLK, /*0x14*/ IPS, /*0x18*/ IPS, /*0x1C*/ IPS,
/*0x20*/ IPS, /*0x24*/ IPS, /*0x28*/ IPS, /*0x2C*/ HCLK,
/*0x30*/ IPS, /*0x34*/ IPS, /*0x38*/ IPS, /*0x3C*/ IPS,
/*0x40*/ IPS, /*0x44*/ IPS, /*0x48*/ IPS, /*0x4C*/ IPS,
/*0x50*/ IPS, /*0x54*/ IPS, /*0x58*/ IPS, /*0x5C*/ HCLK,
/*0x60*/ HCLK, /*0x64*/ HCLK, /*0x68*/ HCLK, /*0x6C*/ HCLK,
/*0x70*/ IPS, /*0x74*/ IPS, /*0x78*/ IPS, /*0x7C*/ IPS,
/*0x80*/ HCLK, /*0x84*/ IPS, /*0x88*/ IPS
};
#undef IPS
#undef HCLK
static const u32 clockSourceSize = sizeof(clockSource)/sizeof(clockSource[0]);
u32 clearmask = 0;
offset /= 4;
if( offset < clockSourceSize && clockSource[offset] /* == HCLK */ )
{
u32 val = ENCHW_READ_REG32( enchw, 0 );
clearmask = ~val & (1<<12);
ENCHW_WRITE_REG32( enchw, 0, val | 1<<12 );
}
return clearmask;
}
/*------------------------------------------------------------------------------
RestoreRegAccess
------------------------------------------------------------------------------*/
static __inline void RestoreRegAccess( EncHw_t* enchw, u32 clearmask )
{
if( clearmask ) ENCHW_REG32(enchw,0) &= ~clearmask;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -