Files
SDK_SG200x_V2/u-boot-2021.10/drivers/jpeg/jpuapi.c
sophgo-forum-service 17580ae06a u-boot: weekly rls 2024.05.22
- bf9a0a

Change-Id: I0d8f19b2dfb78faf564af12d311557ac18b74c4d
2024-05-31 14:44:04 +08:00

1835 lines
43 KiB
C

#include "jpuapi.h"
#include "jpuapifunc.h"
#include "jpulog.h"
#include "dm/device.h"
#include "timer.h"
static unsigned char sJpuCompInfoTable[5][24] = {
{00, 02, 02, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 420
{00, 02, 01, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 422H
{00, 01, 02, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 422V
{00, 01, 01, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 444
{00, 01, 01, 00, 00, 00, 01, 00, 00, 00, 00, 00,
02, 00, 00, 00, 00, 00, 03, 00, 00, 00, 00, 00}, // 400
};
int JPU_IsBusy(void)
{
Uint32 val;
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
if ((val & (1 << INT_JPU_DONE)) || (val & (1 << INT_JPU_ERROR)))
return 0;
return 1;
}
void JPU_ClrStatus(Uint32 val)
{
if (val != 0)
JpuWriteReg(MJPEG_PIC_STATUS_REG, val);
}
Uint32 JPU_GetStatus(void)
{
return JpuReadReg(MJPEG_PIC_STATUS_REG);
}
Uint32 JPU_IsInit(void)
{
jpu_instance_pool_t *pjip;
pjip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!pjip)
return 0;
return 1;
}
Uint32 JPU_WaitInterrupt(int timeout)
{
Uint32 reason = 0;
#ifdef SUPPORT_INTERRUPT
reason = jdi_wait_interrupt(timeout);
BM_DBG_TRACE("reason = 0x%X\n", reason);
#else
reason = jdi_wait_interrupt(timeout);
BM_DBG_TRACE("reason = 0x%X\n", reason);
JpgSetClockGate(1);
if (reason != (Uint32)-1)
reason = JpuReadReg(MJPEG_PIC_STATUS_REG);
JpgSetClockGate(0);
#endif
return reason;
}
int JPU_GetOpenInstanceNum(void)
{
jpu_instance_pool_t *pjip;
pjip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!pjip)
return -1;
return pjip->jpu_instance_num;
}
JpgRet JPU_Init(void)
{
jpu_instance_pool_t *pjip;
if (jdi_init() < 0)
return JPG_RET_FAILURE;
pjip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!pjip)
return JPG_RET_FAILURE;
InitJpgInstancePool();
JPU_SWReset();
return JPG_RET_SUCCESS;
}
void JPU_DeInit(void)
{
jdi_release();
}
JpgRet JPU_GetVersionInfo(Uint32 *versionInfo)
{
if (JPU_IsInit() == 0) {
return JPG_RET_NOT_INITIALIZED;
}
*versionInfo = API_VERSION;
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecOpen(JpgDecHandle *pHandle, JpgDecOpenParam *pop)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
ret = CheckJpgDecOpenParam(pop);
if (ret != JPG_RET_SUCCESS) {
return ret;
}
ret = GetJpgInstance(&pJpgInst);
if (ret == JPG_RET_FAILURE) {
*pHandle = 0;
JpgLeaveLock();
return JPG_RET_FAILURE;
}
*pHandle = pJpgInst;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
memset(pDecInfo, 0x00, sizeof(JpgDecInfo));
pDecInfo->streamWrPtr = pop->bitstreamBuffer;
pDecInfo->streamRdPtr = pop->bitstreamBuffer;
pDecInfo->streamBufStartAddr = pop->bitstreamBuffer;
pDecInfo->streamBufSize = pop->bitstreamBufferSize;
pDecInfo->streamBufEndAddr =
pop->bitstreamBuffer + pop->bitstreamBufferSize;
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pDecInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamBufEndAddr);
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pDecInfo->streamRdPtr);
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pDecInfo->streamWrPtr);
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0);
pDecInfo->pBitStream = pop->pBitStream;
pDecInfo->streamEndian = pop->streamEndian;
pDecInfo->frameEndian = pop->frameEndian;
pDecInfo->chroma_interleave = pop->chroma_interleave;
pDecInfo->packedFormat = pop->packedFormat;
pDecInfo->roiEnable = pop->roiEnable;
pDecInfo->roiWidth = pop->roiWidth;
pDecInfo->roiHeight = pop->roiHeight;
pDecInfo->roiOffsetX = pop->roiOffsetX;
pDecInfo->roiOffsetY = pop->roiOffsetY;
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecClose(JpgDecHandle handle)
{
JpgInst *pJpgInst;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
JpgEnterLock();
FreeJpgInstance(pJpgInst);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecGetInitialInfo(JpgDecHandle handle, JpgDecInitialInfo *info)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS) {
BM_DBG_ERR("CheckJpgInstValidity\n");
return ret;
}
if (info == 0) {
return JPG_RET_INVALID_PARAM;
}
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
if (JpegDecodeHeader(pDecInfo) <= 0) {
BM_DBG_ERR("JpegDecodeHeader\n");
return JPG_RET_FAILURE;
}
info->picWidth = pDecInfo->picWidth;
info->picHeight = pDecInfo->picHeight;
info->minFrameBufferCount = 1;
info->sourceFormat = pDecInfo->format;
info->ecsPtr = pDecInfo->ecsPtr;
JLOG(ERR, "pDecInfo->format %d\n", pDecInfo->format);
pDecInfo->initialInfoObtained = 1;
pDecInfo->minFrameBufferNum = 1;
#ifdef MJPEG_ERROR_CONCEAL
pDecInfo->curRstIdx = 0;
pDecInfo->nextRstIdx = -1;
#endif
if (pDecInfo->packedFormat == PACKED_FORMAT_444 &&
pDecInfo->format != FORMAT_444) {
return JPG_RET_INVALID_PARAM;
}
if (pDecInfo->roiEnable) {
pDecInfo->roiMcuWidth = pDecInfo->roiWidth / pDecInfo->mcuWidth;
pDecInfo->roiMcuHeight = pDecInfo->roiHeight / pDecInfo->mcuHeight;
pDecInfo->roiMcuOffsetX = pDecInfo->roiOffsetX / pDecInfo->mcuWidth;
pDecInfo->roiMcuOffsetY = pDecInfo->roiOffsetY / pDecInfo->mcuHeight;
if (pDecInfo->roiOffsetX > pDecInfo->alignedWidth ||
pDecInfo->roiOffsetY > pDecInfo->alignedHeight ||
pDecInfo->roiOffsetX + pDecInfo->roiWidth > pDecInfo->alignedWidth ||
pDecInfo->roiOffsetY + pDecInfo->roiHeight > pDecInfo->alignedHeight)
return JPG_RET_INVALID_PARAM;
if (((pDecInfo->roiOffsetX + pDecInfo->roiWidth) < pDecInfo->mcuWidth) ||
((pDecInfo->roiOffsetY + pDecInfo->roiHeight) < pDecInfo->mcuHeight))
return JPG_RET_INVALID_PARAM;
info->roiFrameWidth = pDecInfo->roiMcuWidth * pDecInfo->mcuWidth;
info->roiFrameHeight = pDecInfo->roiMcuHeight * pDecInfo->mcuHeight;
info->roiFrameOffsetX = pDecInfo->roiMcuOffsetX * pDecInfo->mcuWidth;
info->roiFrameOffsetY = pDecInfo->roiMcuOffsetY * pDecInfo->mcuHeight;
info->roiMCUSize = pDecInfo->mcuWidth;
}
info->colorComponents = pDecInfo->compNum;
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecRegisterFrameBuffer(JpgDecHandle handle, FrameBuffer *bufArray,
int num, int strideY, int strideC)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
if (!pDecInfo->initialInfoObtained) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
if (bufArray == 0) {
return JPG_RET_INVALID_FRAME_BUFFER;
}
if (num < pDecInfo->minFrameBufferNum) {
return JPG_RET_INSUFFICIENT_FRAME_BUFFERS;
}
if (pDecInfo->usePartial && pDecInfo->bufNum == 0) {
return JPG_RET_INSUFFICIENT_FRAME_BUFFERS;
}
if (pDecInfo->usePartial && num < pDecInfo->bufNum) {
return JPG_RET_INSUFFICIENT_FRAME_BUFFERS;
}
if (!pDecInfo->roiEnable) {
if (strideY < pDecInfo->picWidth >> 3 || strideY % 8 != 0)
return JPG_RET_INVALID_STRIDE;
}
pDecInfo->frameBufPool = bufArray;
pDecInfo->numFrameBuffers = num;
pDecInfo->stride = strideY;
pDecInfo->strideY = strideY;
pDecInfo->strideC = strideC;
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecGetBitstreamBuffer(JpgDecHandle handle, PhysicalAddress *prdPrt,
PhysicalAddress *pwrPtr, int *size)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
PhysicalAddress rdPtr;
PhysicalAddress wrPtr;
int room;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
if (prdPrt == 0 || pwrPtr == 0 || size == 0) {
return JPG_RET_INVALID_PARAM;
}
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
if (GetJpgPendingInst() == pJpgInst) {
rdPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
} else {
rdPtr = pDecInfo->streamRdPtr;
}
wrPtr = pDecInfo->streamWrPtr;
if (wrPtr == pDecInfo->streamBufStartAddr) {
if (pDecInfo->frameOffset == 0) {
room = (pDecInfo->streamBufEndAddr -= pDecInfo->streamBufStartAddr);
} else {
room = (pDecInfo->frameOffset);
}
} else {
room = (pDecInfo->streamBufEndAddr - wrPtr);
}
room = ((room >> 9) << 9); // multiple of 512
*prdPrt = rdPtr;
*pwrPtr = wrPtr;
*size = room;
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecUpdateBitstreamBuffer(JpgDecHandle handle, int size)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
PhysicalAddress wrPtr;
PhysicalAddress rdPtr;
JpgRet ret;
int val = 0;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
wrPtr = pDecInfo->streamWrPtr;
if (size == 0) {
val = (wrPtr - pDecInfo->streamBufStartAddr) / 256;
if ((wrPtr - pDecInfo->streamBufStartAddr) % 256)
val = val + 1;
if (GetJpgPendingInst() == pJpgInst)
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, (1 << 31 | val));
pDecInfo->streamEndflag = 1;
return JPG_RET_SUCCESS;
}
JpgSetClockGate(1);
wrPtr = pDecInfo->streamWrPtr;
wrPtr += size;
if (wrPtr == pDecInfo->streamBufEndAddr) {
wrPtr = pDecInfo->streamBufStartAddr;
}
pDecInfo->streamWrPtr = wrPtr;
if (GetJpgPendingInst() == pJpgInst) {
rdPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
if (rdPtr == (pDecInfo->streamBufEndAddr & 0xffffffff)) {
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
}
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, wrPtr);
if (wrPtr == pDecInfo->streamBufStartAddr) {
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamBufEndAddr);
} else {
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, wrPtr);
}
} else {
rdPtr = pDecInfo->streamRdPtr;
}
pDecInfo->streamRdPtr = rdPtr;
JpgSetClockGate(0);
return JPG_RET_SUCCESS;
}
JpgRet JPU_SWReset(void)
{
Uint32 val;
PhysicalAddress streamBufStartAddr;
PhysicalAddress streamBufEndAddr;
PhysicalAddress streamWrPtr;
PhysicalAddress streamRdPtr;
JpgEnterLock();
streamBufStartAddr = JpuReadReg(MJPEG_BBC_BAS_ADDR_REG);
streamBufEndAddr = JpuReadReg(MJPEG_BBC_END_ADDR_REG);
streamWrPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
streamRdPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_INIT));
do {
val = JpuReadReg(MJPEG_PIC_START_REG);
} while ((val & (1 << JPG_START_INIT)) == (1 << JPG_START_INIT));
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, streamBufEndAddr);
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, streamRdPtr);
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, streamWrPtr);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_HWReset(void)
{
if (jdi_hw_reset() < 0)
return JPG_RET_FAILURE;
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecIssueStop(JpgDecHandle handle)
{
JpgInst *pJpgInst;
// JpgDecInfo * pDecInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
// pDecInfo = &pJpgInst->JpgInfo.decInfo;
if (pJpgInst != GetJpgPendingInst()) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
JpgSetClockGate(1);
JpuWriteReg(MJPEG_PIC_START_REG, 1 << JPG_START_STOP);
JpgSetClockGate(0);
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecCompleteStop(JpgDecHandle handle)
{
JpgInst *pJpgInst;
// JpgDecInfo * pDecInfo;
JpgRet ret;
Uint32 val;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
// pDecInfo = &pJpgInst->JpgInfo.decInfo;
if (pJpgInst != GetJpgPendingInst()) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
JpgSetClockGate(1);
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
if (val & (1 << INT_JPU_BIT_BUF_STOP)) {
SetJpgPendingInst(0);
JpgSetClockGate(0);
} else {
JpgSetClockGate(0);
return JPG_RET_WRONG_CALL_SEQUENCE;
}
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecSetRdPtr(JpgDecHandle handle, PhysicalAddress addr, int updateWrPtr)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
JpgEnterLock();
if (GetJpgPendingInst()) {
JpgLeaveLock();
return JPG_RET_FRAME_NOT_COMPLETE;
}
pDecInfo->streamRdPtr = addr;
if (updateWrPtr)
pDecInfo->streamWrPtr = addr;
pDecInfo->frameOffset = addr - pDecInfo->streamBufStartAddr;
pDecInfo->consumeByte = 0;
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pDecInfo->streamRdPtr);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecStartOneFrame(JpgDecHandle handle, JpgDecParam *param)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
Uint32 rotMir;
JpgRet ret;
Uint32 val;
int i;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
if (pDecInfo->frameBufPool == 0) { // This means frame buffers have not been registered.
return JPG_RET_WRONG_CALL_SEQUENCE;
}
rotMir = 0;
if (pDecInfo->rotationEnable) {
rotMir |= 0x10; // Enable rotator
switch (pDecInfo->rotationAngle) {
case 0:
rotMir |= 0x0;
break;
case 90:
rotMir |= 0x1;
break;
case 180:
rotMir |= 0x2;
break;
case 270:
rotMir |= 0x3;
break;
}
}
if (pDecInfo->mirrorEnable) {
rotMir |= 0x10; // Enable rotator
switch (pDecInfo->mirrorDirection) {
case MIRDIR_NONE:
rotMir |= 0x0;
break;
case MIRDIR_VER:
rotMir |= 0x4;
break;
case MIRDIR_HOR:
rotMir |= 0x8;
break;
case MIRDIR_HOR_VER:
rotMir |= 0xc;
break;
}
}
JpgEnterLock();
if (GetJpgPendingInst()) {
JpgLeaveLock();
return JPG_RET_FRAME_NOT_COMPLETE;
}
#ifdef MJPEG_ERROR_CONCEAL
// Error Concealment
if (pDecInfo->errInfo.bError) {
// error conceal main function
val = JpegDecodeConcealError(pDecInfo);
if (val == -1) {
// stream buffer wrap around in error cases.
pDecInfo->frameOffset = 0;
pDecInfo->nextOffset = 0;
// end of stream
if (pDecInfo->streamEndflag == 1) {
pDecInfo->frameOffset = -1;
SetJpgPendingInst(pJpgInst);
return JPG_RET_EOS;
}
// request data
JpgLeaveLock();
return JPG_RET_BIT_EMPTY;
}
// init GBU
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
val = pDecInfo->huffAcIdx << 10 | pDecInfo->huffDcIdx << 7 | pDecInfo->userHuffTab << 6;
val |= (JPU_CHECK_WRITE_RESPONSE_BVALID_SIGNAL << 2) | 0;
JpuWriteReg(MJPEG_PIC_CTRL_REG, val);
val = pDecInfo->mcuBlockNum << 16 | pDecInfo->compNum << 12;
val |= pDecInfo->compInfo[0] << 8 | pDecInfo->compInfo[1] << 4 | pDecInfo->compInfo[2];
JpuWriteReg(MJPEG_MCU_INFO_REG, val);
JpuWriteReg(MJPEG_RST_INTVAL_REG, pDecInfo->rstIntval);
JpgDecGramSetup(pDecInfo);
JpuWriteReg(MJPEG_DPCM_DIFF_Y_REG, 0);
JpuWriteReg(MJPEG_DPCM_DIFF_CB_REG, 0);
JpuWriteReg(MJPEG_DPCM_DIFF_CR_REG, 0);
JpuWriteReg(MJPEG_GBU_FF_RPTR_REG, pDecInfo->bitPtr);
JpuWriteReg(MJPEG_GBU_CTRL_REG, 3);
val = (pDecInfo->setPosX << 16) | (pDecInfo->setPosY);
JpuWriteReg(MJPEG_PIC_SETMB_REG, val);
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC));
SetJpgPendingInst(pJpgInst);
return JPG_RET_SUCCESS;
}
#endif
if (pDecInfo->frameOffset < 0) {
SetJpgPendingInst(pJpgInst);
return JPG_RET_EOS;
}
val = JpegDecodeHeader(pDecInfo);
if (val == 0) {
JpgLeaveLock();
return JPG_RET_FAILURE;
}
if (val == -2) { // wrap around case
pDecInfo->frameOffset = 0;
pDecInfo->ecsPtr = 0;
#ifdef MJPEG_ERROR_CONCEAL
pDecInfo->nextOffset = 0;
#endif
val = JpegDecodeHeader(pDecInfo);
if (val == 0) {
JpgLeaveLock();
return JPG_RET_FAILURE;
}
}
if (val == -1) { // stream empty case
if (pDecInfo->streamEndflag == 1) {
SetJpgPendingInst(pJpgInst);
pDecInfo->frameOffset = -1;
return JPG_RET_EOS;
}
JpgLeaveLock();
return JPG_RET_BIT_EMPTY;
}
if (pDecInfo->streamRdPtr == pDecInfo->streamBufEndAddr) {
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
}
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pDecInfo->streamWrPtr);
if (pDecInfo->streamWrPtr == pDecInfo->streamBufStartAddr) {
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamBufEndAddr);
} else {
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamWrPtr);
}
JLOG(INFO, "pDecInfo->streamBufStartAddr %p\n",
(void *)pDecInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pDecInfo->streamBufStartAddr);
if (pDecInfo->streamEndflag == 1) {
val = JpuReadReg(MJPEG_BBC_STRM_CTRL_REG);
if ((val & (1 << 31)) == 0) {
val = (pDecInfo->streamWrPtr -
pDecInfo->streamBufStartAddr) /
256;
if ((pDecInfo->streamWrPtr -
pDecInfo->streamBufStartAddr) %
256)
val = val + 1;
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, (1 << 31 | val));
}
} else {
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0);
}
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
JpuWriteReg(MJPEG_PIC_ERRMB_REG, 0);
val = pDecInfo->huffAcIdx << 10 | pDecInfo->huffDcIdx << 7 | pDecInfo->userHuffTab << 6;
val |= ((JPU_CHECK_WRITE_RESPONSE_BVALID_SIGNAL << 2) | pDecInfo->usePartial);
JpuWriteReg(MJPEG_PIC_CTRL_REG, val);
JpuWriteReg(MJPEG_PIC_SIZE_REG, (pDecInfo->alignedWidth << 16) | pDecInfo->alignedHeight);
JpuWriteReg(MJPEG_ROT_INFO_REG, 0);
JpuWriteReg(MJPEG_OP_INFO_REG, pDecInfo->lineNum << 16 | pDecInfo->bufNum << 3 | pDecInfo->busReqNum);
val = pDecInfo->mcuBlockNum << 16 | pDecInfo->compNum << 12;
val |= pDecInfo->compInfo[0] << 8 | pDecInfo->compInfo[1] << 4 | pDecInfo->compInfo[2];
JpuWriteReg(MJPEG_MCU_INFO_REG, val);
if (pDecInfo->chroma_interleave == 0)
val = 0;
else if (pDecInfo->chroma_interleave == 1)
val = 2;
else
val = 3;
if (pDecInfo->packedFormat == PACKED_FORMAT_NONE) {
val |= (pDecInfo->frameEndian << 6) | (0 << 5) | (0 << 4);
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
} else if (pDecInfo->packedFormat == PACKED_FORMAT_444) {
val |= (pDecInfo->frameEndian << 6) | (1 << 5) | (0 << 4) | (0 << 2);
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
} else {
val |= (pDecInfo->frameEndian << 6) | (0 << 5) | (1 << 4) | ((pDecInfo->packedFormat - 1) << 2);
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
}
JpuWriteReg(MJPEG_RST_INTVAL_REG, pDecInfo->rstIntval);
if (param) {
if (param->scaleDownRatioWidth > 0)
pDecInfo->iHorScaleMode = param->scaleDownRatioWidth;
if (param->scaleDownRatioHeight > 0)
pDecInfo->iVerScaleMode = param->scaleDownRatioHeight;
}
if (pDecInfo->iHorScaleMode | pDecInfo->iVerScaleMode)
val = ((pDecInfo->iHorScaleMode & 0x3) << 2) |
((pDecInfo->iVerScaleMode & 0x3)) | 0x10;
else {
val = 0;
}
JpuWriteReg(MJPEG_SCL_INFO_REG, val);
if (pDecInfo->userHuffTab) {
if (!JpgDecHuffTabSetUp(pDecInfo)) {
JpgLeaveLock();
return JPG_RET_INVALID_PARAM;
}
}
if (!JpgDecQMatTabSetUp(pDecInfo)) {
JpgLeaveLock();
return JPG_RET_INVALID_PARAM;
}
JpgDecGramSetup(pDecInfo);
JpuWriteReg(MJPEG_RST_INDEX_REG, 0); // RST index at the beginning.
JpuWriteReg(MJPEG_RST_COUNT_REG, 0);
JpuWriteReg(MJPEG_DPCM_DIFF_Y_REG, 0);
JpuWriteReg(MJPEG_DPCM_DIFF_CB_REG, 0);
JpuWriteReg(MJPEG_DPCM_DIFF_CR_REG, 0);
JpuWriteReg(MJPEG_GBU_FF_RPTR_REG, pDecInfo->bitPtr);
JpuWriteReg(MJPEG_GBU_CTRL_REG, 3);
JpuWriteReg(MJPEG_ROT_INFO_REG, rotMir);
if (rotMir & 1) {
pDecInfo->format = (pDecInfo->format == FORMAT_422)
? FORMAT_224
: (pDecInfo->format == FORMAT_224)
? FORMAT_422
: pDecInfo->format;
}
if (rotMir & 0x10) {
JpuWriteReg(MJPEG_DPB_BASE00_REG, pDecInfo->rotatorOutput.bufY);
JpuWriteReg(MJPEG_DPB_BASE01_REG,
pDecInfo->rotatorOutput.bufCb);
JpuWriteReg(MJPEG_DPB_BASE02_REG,
pDecInfo->rotatorOutput.bufCr);
} else if (pDecInfo->usePartial) {
PhysicalAddress addr;
val = (pDecInfo->frameIdx % (pDecInfo->numFrameBuffers / pDecInfo->bufNum));
for (i = 0; i < pDecInfo->bufNum; i++) {
addr = pDecInfo->frameBufPool[(val * pDecInfo->bufNum) + i].bufY;
JpuWriteReg(MJPEG_DPB_BASE00_REG + (i * 12), addr);
addr = pDecInfo->frameBufPool[(val * pDecInfo->bufNum) + i].bufCb;
JpuWriteReg(MJPEG_DPB_BASE01_REG + (i * 12), addr);
addr = pDecInfo->frameBufPool[(val * pDecInfo->bufNum) + i].bufCr;
JpuWriteReg(MJPEG_DPB_BASE02_REG + (i * 12), addr);
}
} else {
val = (pDecInfo->frameIdx % pDecInfo->numFrameBuffers);
JpuWriteReg(MJPEG_DPB_BASE00_REG, pDecInfo->frameBufPool[val].bufY);
JpuWriteReg(MJPEG_DPB_BASE01_REG, pDecInfo->frameBufPool[val].bufCb);
JpuWriteReg(MJPEG_DPB_BASE02_REG, pDecInfo->frameBufPool[val].bufCr);
}
if (pDecInfo->rotationEnable) {
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pDecInfo->rotatorStride);
val = (pDecInfo->format == FORMAT_420 ||
pDecInfo->format == FORMAT_422 ||
pDecInfo->format == FORMAT_400)
? 2
: 1;
if (pDecInfo->chroma_interleave)
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, (pDecInfo->rotatorStride / (int)val) * 2);
else
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pDecInfo->rotatorStride / (int)val);
} else {
CVI_JPG_DBG("packedFormat = %d\n", pDecInfo->packedFormat);
if (pDecInfo->packedFormat == PACKED_FORMAT_NONE && pDecInfo->format == FORMAT_420) {
CVI_JPG_DBG("strideY = %d, strideC = %d\n", pDecInfo->strideY, pDecInfo->strideC);
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pDecInfo->strideY);
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pDecInfo->strideC);
} else {
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pDecInfo->stride);
if (pDecInfo->chroma_interleave)
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, (pDecInfo->stride / (int)val) * 2);
else
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pDecInfo->stride / (int)val);
}
}
if (pDecInfo->roiEnable) {
JpuWriteReg(MJPEG_CLP_INFO_REG, 1);
JpuWriteReg(MJPEG_CLP_BASE_REG, pDecInfo->roiOffsetX << 16 | pDecInfo->roiOffsetY); // pixel unit
val = (pDecInfo->roiMcuWidth * pDecInfo->mcuWidth) << 16;
val |= pDecInfo->roiMcuHeight * pDecInfo->mcuHeight;
JpuWriteReg(MJPEG_CLP_SIZE_REG, val); // pixel Unit
} else {
JpuWriteReg(MJPEG_CLP_INFO_REG, 0);
}
if (pJpgInst->loggingEnable)
jdi_log(JDI_LOG_CMD_PICRUN, 1);
BM_DBG_FLOW("JPG_START_PIC\n");
#ifdef PROFILE_PERFORMANCE
timer_meter_start();
#endif
JpuWriteReg(MJPEG_PIC_STATUS_REG, JpuReadReg(MJPEG_PIC_STATUS_REG));
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC));
SetJpgPendingInst(pJpgInst);
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecGetOutputInfo(JpgDecHandle handle, JpgDecOutputInfo *info)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
Uint32 val = 0;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS) {
SetJpgPendingInst(0);
JpgLeaveLock();
return ret;
}
if (info == 0) {
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_INVALID_PARAM;
}
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
if (pJpgInst != GetJpgPendingInst()) {
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_WRONG_CALL_SEQUENCE;
}
if (pDecInfo->frameOffset < 0) {
info->numOfErrMBs = 0;
info->decodingSuccess = 1;
info->indexFrameDisplay = -1;
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
if (pDecInfo->roiEnable) {
info->decPicWidth = pDecInfo->roiMcuWidth * pDecInfo->mcuWidth;
info->decPicHeight =
pDecInfo->roiMcuHeight * pDecInfo->mcuHeight;
} else {
info->decPicWidth = pDecInfo->alignedWidth;
info->decPicHeight = pDecInfo->alignedHeight;
}
info->decPicWidth >>= pDecInfo->iHorScaleMode;
info->decPicHeight >>= pDecInfo->iVerScaleMode;
info->indexFrameDisplay =
(pDecInfo->frameIdx % pDecInfo->numFrameBuffers);
#ifdef MJPEG_ERROR_CONCEAL
info->consumedByte =
pDecInfo->gbuStartPtr + (JpuReadReg(MJPEG_GBU_TT_CNT_REG)) / 8;
#else
info->consumedByte = (JpuReadReg(MJPEG_GBU_TT_CNT_REG)) / 8;
#endif
pDecInfo->streamRdPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
pDecInfo->consumeByte = info->consumedByte - 16 - pDecInfo->ecsPtr;
info->bytePosFrameStart = pDecInfo->frameOffset;
info->ecsPtr = pDecInfo->ecsPtr;
pDecInfo->ecsPtr = 0;
pDecInfo->frameIdx++;
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
if (val & (1 << INT_JPU_DONE)) {
info->decodingSuccess = 1;
info->numOfErrMBs = 0;
#ifdef MJPEG_ERROR_CONCEAL
pDecInfo->errInfo.bError = 0;
pDecInfo->nextOffset = 0;
pDecInfo->gbuStartPtr = 0;
#endif
} else if (val & (1 << INT_JPU_ERROR)) {
info->numOfErrMBs = JpuReadReg(MJPEG_PIC_ERRMB_REG);
info->decodingSuccess = 0;
#ifdef MJPEG_ERROR_CONCEAL
// info->numOfErrMBs =
// JpuReadReg(MJPEG_PIC_ERRMB_REG);
pDecInfo->errInfo.bError = 1;
pDecInfo->errInfo.errPosY = info->numOfErrMBs & 0xFFF;
pDecInfo->errInfo.errPosX = (info->numOfErrMBs >> 12) & 0xFFF;
// set search point to find next rstMarker from origin of frame
// buffer by host
pDecInfo->nextOffset = (info->consumedByte) & (~7);
// prevent to find same position.
if (pDecInfo->currOffset == pDecInfo->nextOffset)
pDecInfo->nextOffset += JPU_GBU_SIZE;
#endif
}
if (val != 0)
JpuWriteReg(MJPEG_PIC_STATUS_REG, val);
if (pJpgInst->loggingEnable) {
jdi_log(JDI_LOG_CMD_PICRUN, 0);
}
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_DecGiveCommand(JpgDecHandle handle, JpgCommand cmd, void *param)
{
JpgInst *pJpgInst;
JpgDecInfo *pDecInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pDecInfo = &pJpgInst->JpgInfo.decInfo;
switch (cmd) {
case ENABLE_JPG_ROTATION: {
if (pDecInfo->roiEnable) {
return JPG_RET_INVALID_PARAM;
}
if (pDecInfo->rotatorStride == 0) {
return JPG_RET_ROTATOR_STRIDE_NOT_SET;
}
pDecInfo->rotationEnable = 1;
break;
}
case DISABLE_JPG_ROTATION: {
pDecInfo->rotationEnable = 0;
break;
}
case ENABLE_JPG_MIRRORING: {
if (pDecInfo->rotatorStride == 0) {
return JPG_RET_ROTATOR_STRIDE_NOT_SET;
}
pDecInfo->mirrorEnable = 1;
break;
}
case DISABLE_JPG_MIRRORING: {
pDecInfo->mirrorEnable = 0;
break;
}
case SET_JPG_MIRROR_DIRECTION: {
JpgMirrorDirection mirDir;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
mirDir = *(JpgMirrorDirection *)param;
if (!(mirDir >= MIRDIR_NONE && mirDir <= MIRDIR_HOR_VER)) {
return JPG_RET_INVALID_PARAM;
}
pDecInfo->mirrorDirection = mirDir;
break;
}
case SET_JPG_ROTATION_ANGLE: {
int angle;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
angle = *(int *)param;
if (angle != 0 && angle != 90 && angle != 180 && angle != 270) {
return JPG_RET_INVALID_PARAM;
}
pDecInfo->rotationAngle = angle;
break;
}
case SET_JPG_ROTATOR_OUTPUT: {
FrameBuffer *frame;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
frame = (FrameBuffer *)param;
pDecInfo->rotatorOutput = *frame;
pDecInfo->rotatorOutputValid = 1;
break;
}
case SET_JPG_ROTATOR_STRIDE: {
int stride;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
stride = *(int *)param;
if (stride % 8 != 0 || stride == 0) {
return JPG_RET_INVALID_STRIDE;
}
if (pDecInfo->rotationAngle == 90 ||
pDecInfo->rotationAngle == 270) {
if (pDecInfo->alignedHeight > stride) {
return JPG_RET_INVALID_STRIDE;
}
} else {
if (pDecInfo->alignedWidth > stride) {
return JPG_RET_INVALID_STRIDE;
}
}
pDecInfo->rotatorStride = stride;
break;
}
case SET_JPG_SCALE_HOR: {
int scale;
scale = *(int *)param;
if (pDecInfo->alignedWidth < 128 ||
pDecInfo->alignedHeight < 128) {
if (scale) {
return JPG_RET_INVALID_PARAM;
}
}
pDecInfo->iHorScaleMode = scale;
break;
}
case SET_JPG_SCALE_VER: {
int scale;
scale = *(int *)param;
if (pDecInfo->alignedWidth < 128 ||
pDecInfo->alignedHeight < 128) {
if (scale) {
return JPG_RET_INVALID_PARAM;
}
}
pDecInfo->iVerScaleMode = scale;
break;
}
case SET_JPG_USE_PARTIAL_MODE: {
int enable;
enable = *(int *)param;
pDecInfo->usePartial = enable;
break;
}
case SET_JPG_PARTIAL_FRAME_NUM: {
int frame;
if (pDecInfo->stride != 0) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
frame = *(int *)param;
pDecInfo->bufNum = frame;
break;
}
case SET_JPG_PARTIAL_LINE_NUM: {
int line;
if (pDecInfo->stride != 0) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
line = *(int *)param;
pDecInfo->lineNum = line;
break;
}
case ENABLE_LOGGING: {
pJpgInst->loggingEnable = 1;
} break;
case DISABLE_LOGGING: {
pJpgInst->loggingEnable = 0;
} break;
default:
return JPG_RET_INVALID_COMMAND;
}
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncOpen(JpgEncHandle *pHandle, JpgEncOpenParam *pop)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
JpgRet ret;
int i;
ret = CheckJpgEncOpenParam(pop);
if (ret != JPG_RET_SUCCESS) {
BM_DBG_ERR("CheckJpgEncOpenParam\n");
return ret;
}
JpgEnterLock();
ret = GetJpgInstance(&pJpgInst);
if (ret == JPG_RET_FAILURE) {
BM_DBG_ERR("GetJpgInstance\n");
*pHandle = 0;
JpgLeaveLock();
return JPG_RET_FAILURE;
}
*pHandle = pJpgInst;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
memset(pEncInfo, 0x00, sizeof(JpgEncInfo));
pEncInfo->openParam = *pop;
pEncInfo->streamRdPtr = pop->bitstreamBuffer;
pEncInfo->streamWrPtr = pop->bitstreamBuffer;
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pEncInfo->streamWrPtr);
pEncInfo->streamBufStartAddr = pop->bitstreamBuffer;
pEncInfo->streamBufSize = pop->bitstreamBufferSize;
pEncInfo->streamBufEndAddr =
pop->bitstreamBuffer + pop->bitstreamBufferSize;
pEncInfo->streamEndian = pop->streamEndian;
pEncInfo->frameEndian = pop->frameEndian;
pEncInfo->chroma_interleave = pop->chroma_interleave;
pEncInfo->format = pEncInfo->openParam.sourceFormat;
pEncInfo->picWidth = pEncInfo->openParam.picWidth;
pEncInfo->picHeight = pEncInfo->openParam.picHeight;
// Picture size alignment
if (pEncInfo->format == FORMAT_420 || pEncInfo->format == FORMAT_422)
pEncInfo->alignedWidth = ((pEncInfo->picWidth + 15) / 16) * 16;
else
pEncInfo->alignedWidth = ((pEncInfo->picWidth + 7) / 8) * 8;
if (pEncInfo->format == FORMAT_420 || pEncInfo->format == FORMAT_224)
pEncInfo->alignedHeight =
((pEncInfo->picHeight + 15) / 16) * 16;
else
pEncInfo->alignedHeight = ((pEncInfo->picHeight + 7) / 8) * 8;
pEncInfo->rstIntval = pEncInfo->openParam.restartInterval;
for (i = 0; i < 4; i++)
pEncInfo->pHuffVal[i] = pEncInfo->openParam.huffVal[i];
for (i = 0; i < 4; i++)
pEncInfo->pHuffBits[i] = pEncInfo->openParam.huffBits[i];
for (i = 0; i < 4; i++)
pEncInfo->pQMatTab[i] = pEncInfo->openParam.qMatTab[i];
pEncInfo->pCInfoTab[0] = sJpuCompInfoTable[/*2*/ pEncInfo->format];
pEncInfo->pCInfoTab[1] = pEncInfo->pCInfoTab[0] + 6;
pEncInfo->pCInfoTab[2] = pEncInfo->pCInfoTab[1] + 6;
pEncInfo->pCInfoTab[3] = pEncInfo->pCInfoTab[2] + 6;
if (pop->packedFormat == PACKED_FORMAT_444 &&
pEncInfo->format != FORMAT_444) {
BM_DBG_ERR("PACKED_FORMAT_444\n");
return JPG_RET_INVALID_PARAM;
}
pEncInfo->packedFormat = pop->packedFormat;
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncClose(JpgEncHandle handle)
{
JpgInst *pJpgInst;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
JpgEnterLock();
if (GetJpgPendingInst()) {
JpgLeaveLock();
return JPG_RET_FRAME_NOT_COMPLETE;
}
pJpgInst = handle;
JpuWriteReg(MJPEG_BBC_FLUSH_CMD_REG, 0);
FreeJpgInstance(pJpgInst);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncGetInitialInfo(JpgEncHandle handle, JpgEncInitialInfo *info)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
if (info == 0) {
return JPG_RET_INVALID_PARAM;
}
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
if (pEncInfo->initialInfoObtained) {
return JPG_RET_CALLED_BEFORE;
}
JpgEnterLock();
if (GetJpgPendingInst()) {
JpgLeaveLock();
return JPG_RET_FRAME_NOT_COMPLETE;
}
if (pEncInfo->format == FORMAT_400) {
pEncInfo->compInfo[1] = 0;
pEncInfo->compInfo[2] = 0;
} else {
pEncInfo->compInfo[1] = 5;
pEncInfo->compInfo[2] = 5;
}
if (pEncInfo->format == FORMAT_400)
pEncInfo->compNum = 1;
else
pEncInfo->compNum = 3;
if (pEncInfo->format == FORMAT_420) {
pEncInfo->mcuBlockNum = 6;
pEncInfo->compInfo[0] = 10;
pEncInfo->busReqNum = 2;
} else if (pEncInfo->format == FORMAT_422) {
pEncInfo->mcuBlockNum = 4;
pEncInfo->busReqNum = 3;
pEncInfo->compInfo[0] = 9;
} else if (pEncInfo->format == FORMAT_224) {
pEncInfo->mcuBlockNum = 4;
pEncInfo->busReqNum = 3;
pEncInfo->compInfo[0] = 6;
} else if (pEncInfo->format == FORMAT_444) {
pEncInfo->mcuBlockNum = 3;
pEncInfo->compInfo[0] = 5;
pEncInfo->busReqNum = 4;
} else if (pEncInfo->format == FORMAT_400) {
pEncInfo->mcuBlockNum = 1;
pEncInfo->busReqNum = 4;
pEncInfo->compInfo[0] = 5;
}
info->minFrameBufferCount = 0;
info->colorComponents = pEncInfo->compNum;
pEncInfo->initialInfo = *info;
pEncInfo->initialInfoObtained = 1;
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncGetBitstreamBuffer(JpgEncHandle handle, PhysicalAddress *prdPrt,
PhysicalAddress *pwrPtr, int *size)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
if (prdPrt == 0 || pwrPtr == 0 || size == 0) {
return JPG_RET_INVALID_PARAM;
}
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
JpgSetClockGate(1);
*prdPrt = pEncInfo->streamRdPtr;
if (GetJpgPendingInst() == pJpgInst) {
*pwrPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
} else {
*pwrPtr = pEncInfo->streamWrPtr;
}
*size = *pwrPtr - *prdPrt;
JpgSetClockGate(0);
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncUpdateBitstreamBuffer(JpgEncHandle handle, int size)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
PhysicalAddress rdPtr;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
JpgSetClockGate(1);
rdPtr = pEncInfo->streamRdPtr;
rdPtr += size;
if (rdPtr == pEncInfo->streamBufEndAddr) {
rdPtr = pEncInfo->streamBufStartAddr;
}
pEncInfo->streamRdPtr = pEncInfo->streamBufStartAddr;
if (GetJpgPendingInst() == pJpgInst) {
pEncInfo->streamWrPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
JpuWriteReg(MJPEG_BBC_EXT_ADDR_REG,
pEncInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pEncInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pEncInfo->streamBufStartAddr);
}
JpgSetClockGate(0);
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncIssueStop(JpgEncHandle handle)
{
JpgInst *pJpgInst;
// JpgEncInfo *pEncInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
// pEncInfo = &pJpgInst->JpgInfo.encInfo;
if (pJpgInst != GetJpgPendingInst()) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
JpgSetClockGate(1);
JpuWriteReg(MJPEG_PIC_START_REG, 1 << JPG_START_STOP);
JpgSetClockGate(0);
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncCompleteStop(JpgEncHandle handle)
{
JpgInst *pJpgInst;
// JpgEncInfo *pEncInfo;
JpgRet ret;
Uint32 val;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
// pEncInfo = &pJpgInst->JpgInfo.encInfo;
if (pJpgInst != GetJpgPendingInst()) {
return JPG_RET_WRONG_CALL_SEQUENCE;
}
JpgSetClockGate(1);
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
if (val & (1 << INT_JPU_BIT_BUF_STOP)) {
SetJpgPendingInst(0);
JpgSetClockGate(0);
} else {
JpgSetClockGate(0);
return JPG_RET_WRONG_CALL_SEQUENCE;
}
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncStartOneFrame(JpgEncHandle handle, JpgEncParam *param)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
FrameBuffer *pBasFrame;
Uint32 rotMirEnable;
Uint32 rotMirMode;
JpgRet ret;
Uint32 val;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
ret = CheckJpgEncParam(handle, param);
if (ret != JPG_RET_SUCCESS) {
return ret;
}
pBasFrame = param->sourceFrame;
rotMirEnable = 0;
rotMirMode = 0;
if (pEncInfo->rotationEnable) {
rotMirEnable = 0x10; // Enable rotator
switch (pEncInfo->rotationAngle) {
case 0:
rotMirMode |= 0x0;
break;
case 90:
rotMirMode |= 0x1;
break;
case 180:
rotMirMode |= 0x2;
break;
case 270:
rotMirMode |= 0x3;
break;
}
}
if (pEncInfo->mirrorEnable) {
rotMirEnable = 0x10; // Enable rotator
switch (pEncInfo->mirrorDirection) {
case MIRDIR_NONE:
rotMirMode |= 0x0;
break;
case MIRDIR_VER:
rotMirMode |= 0x4;
break;
case MIRDIR_HOR:
rotMirMode |= 0x8;
break;
case MIRDIR_HOR_VER:
rotMirMode |= 0xc;
break;
}
}
JpgEnterLock();
if (GetJpgPendingInst()) {
JpgLeaveLock();
return JPG_RET_FRAME_NOT_COMPLETE;
}
// off ROI enable due to not supported feature for encoder.
JpuWriteReg(MJPEG_CLP_INFO_REG, 0);
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pEncInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pEncInfo->streamBufEndAddr);
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pEncInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pEncInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
JpuWriteReg(MJPEG_BBC_DATA_CNT_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
JpuWriteReg(MJPEG_BBC_EXT_ADDR_REG, pEncInfo->streamBufStartAddr);
JpuWriteReg(MJPEG_BBC_INT_ADDR_REG, 0);
JpuWriteReg(MJPEG_GBU_BT_PTR_REG, 0);
JpuWriteReg(MJPEG_GBU_WD_PTR_REG, 0);
JpuWriteReg(MJPEG_GBU_BBSR_REG, 0);
JpuWriteReg(MJPEG_GBU_CTRL_REG, 0);
JpuWriteReg(MJPEG_GBU_BBER_REG, ((256 / 4) * 2) - 1);
JpuWriteReg(MJPEG_GBU_BBIR_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
JpuWriteReg(MJPEG_GBU_BBHR_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
val = 0x18 | pEncInfo->usePartial | (JPU_CHECK_WRITE_RESPONSE_BVALID_SIGNAL << 2);
JpuWriteReg(MJPEG_PIC_CTRL_REG, val);
JpuWriteReg(MJPEG_SCL_INFO_REG, 0);
if (pEncInfo->chroma_interleave == 0)
val = 0;
else if (pEncInfo->chroma_interleave == 1)
val = 2;
else
val = 3;
if (pEncInfo->packedFormat == PACKED_FORMAT_NONE) {
val |= (pEncInfo->frameEndian << 6) | (0 << 5) | (0 << 4) | (0 << 2);
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
} else if (pEncInfo->packedFormat == PACKED_FORMAT_444) {
val |= (pEncInfo->frameEndian << 6) | (1 << 5) | (0 << 4) | (0 << 2);
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
} else {
val |= (pEncInfo->frameEndian << 6) | (0 << 5) | (1 << 4) | ((pEncInfo->packedFormat - 1) << 2);
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
}
JpuWriteReg(MJPEG_RST_INTVAL_REG, pEncInfo->rstIntval);
JpuWriteReg(MJPEG_BBC_CTRL_REG, (pEncInfo->streamEndian << 1) | 1);
val = pEncInfo->partiallineNum << 16 | pEncInfo->partialBufNum << 3 | pEncInfo->busReqNum;
JpuWriteReg(MJPEG_OP_INFO_REG, val);
// Load HUFFTab
if (!JpgEncLoadHuffTab(pEncInfo)) {
JpgLeaveLock();
return JPG_RET_INVALID_PARAM;
}
// Load QMATTab
if (!JpgEncLoadQMatTab(pEncInfo)) {
JpgLeaveLock();
return JPG_RET_INVALID_PARAM;
}
JpgEncEncodeHeader(handle, pEncInfo->paraSet);
// although rotator is enable, this picture size must not be changed
// from widh to height.
JpuWriteReg(MJPEG_PIC_SIZE_REG, pEncInfo->alignedWidth << 16 | pEncInfo->alignedHeight);
JpuWriteReg(MJPEG_ROT_INFO_REG, (rotMirEnable | rotMirMode));
val = pEncInfo->mcuBlockNum << 16 | pEncInfo->compNum << 12;
val |= pEncInfo->compInfo[0] << 8 | pEncInfo->compInfo[1] << 4 | pEncInfo->compInfo[2];
JpuWriteReg(MJPEG_MCU_INFO_REG, val);
// JpgEncGbuResetReg
JpuWriteReg(MJPEG_GBU_CTRL_REG, pEncInfo->stuffByteEnable << 3); // stuffing "FF" data where frame end
if (pEncInfo->usePartial) {
int i;
for (i = 0; i < pEncInfo->partialBufNum; i++) {
JpuWriteReg(MJPEG_DPB_BASE00_REG + (i * 12), pBasFrame[i].bufY);
JpuWriteReg(MJPEG_DPB_BASE01_REG + (i * 12), pBasFrame[i].bufCb);
JpuWriteReg(MJPEG_DPB_BASE02_REG + (i * 12), pBasFrame[i].bufCr);
}
} else {
JpuWriteReg(MJPEG_DPB_BASE00_REG, pBasFrame->bufY);
JpuWriteReg(MJPEG_DPB_BASE01_REG, pBasFrame->bufCb);
JpuWriteReg(MJPEG_DPB_BASE02_REG, pBasFrame->bufCr);
}
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pBasFrame->stride);
if (pEncInfo->format == FORMAT_420 || pEncInfo->format == FORMAT_422 || pEncInfo->format == FORMAT_400)
val = 2;
else
val = 1;
if (pEncInfo->chroma_interleave)
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, (pBasFrame->stride / (int)val) * 2);
else
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pBasFrame->stride / (int)val);
if (pJpgInst->loggingEnable)
jdi_log(JDI_LOG_CMD_PICRUN, 1);
#ifdef PROFILE_PERFORMANCE
timer_meter_start();
#endif
JpuWriteReg(MJPEG_PIC_STATUS_REG, JpuReadReg(MJPEG_PIC_STATUS_REG));
if (pEncInfo->usePartial)
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC) | (1 << JPG_START_PARTIAL));
else
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC));
SetJpgPendingInst(pJpgInst);
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncGetOutputInfo(JpgEncHandle handle, JpgEncOutputInfo *info)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
Uint32 val;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS) {
SetJpgPendingInst(0);
JpgLeaveLock();
return ret;
}
if (info == 0) {
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_INVALID_PARAM;
}
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
if (pJpgInst != GetJpgPendingInst()) {
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_WRONG_CALL_SEQUENCE;
}
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
if ((val & 0x4) >> 2) {
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_WRONG_CALL_SEQUENCE;
}
if (val != 0)
JpuWriteReg(MJPEG_PIC_STATUS_REG, val);
info->bitstreamBuffer = pEncInfo->streamBufStartAddr;
info->bitstreamSize = JpuReadReg(MJPEG_BBC_WR_PTR_REG) - pEncInfo->streamBufStartAddr;
pEncInfo->streamWrPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
JpuWriteReg(MJPEG_BBC_FLUSH_CMD_REG, 0);
if (pJpgInst->loggingEnable)
jdi_log(JDI_LOG_CMD_PICRUN, 0);
SetJpgPendingInst(0);
JpgLeaveLock();
return JPG_RET_SUCCESS;
}
JpgRet JPU_EncGiveCommand(JpgEncHandle handle, JpgCommand cmd, void *param)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
JpgRet ret;
ret = CheckJpgInstValidity(handle);
if (ret != JPG_RET_SUCCESS)
return ret;
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
switch (cmd) {
case ENABLE_JPG_ROTATION: {
pEncInfo->rotationEnable = 1;
} break;
case DISABLE_JPG_ROTATION: {
pEncInfo->rotationEnable = 0;
} break;
case ENABLE_JPG_MIRRORING: {
pEncInfo->mirrorEnable = 1;
} break;
case DISABLE_JPG_MIRRORING: {
pEncInfo->mirrorEnable = 0;
} break;
case SET_JPG_MIRROR_DIRECTION: {
JpgMirrorDirection mirDir;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
mirDir = *(JpgMirrorDirection *)param;
if (!(mirDir >= MIRDIR_NONE && mirDir <= MIRDIR_HOR_VER)) {
return JPG_RET_INVALID_PARAM;
}
pEncInfo->mirrorDirection = mirDir;
} break;
case SET_JPG_ROTATION_ANGLE: {
int angle;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
angle = *(int *)param;
if (angle != 0 && angle != 90 && angle != 180 && angle != 270) {
return JPG_RET_INVALID_PARAM;
}
if (pEncInfo->initialInfoObtained && (angle == 90 || angle == 270)) {
return JPG_RET_INVALID_PARAM;
}
pEncInfo->rotationAngle = angle;
} break;
case ENC_JPG_GET_HEADER: {
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
pEncInfo->paraSet = (JpgEncParamSet *)param;
break;
}
case SET_JPG_USE_PARTIAL_MODE: {
int enable;
enable = *(int *)param;
pEncInfo->usePartial = enable;
break;
}
case SET_JPG_PARTIAL_FRAME_NUM: {
int frame;
frame = *(int *)param;
pEncInfo->partialBufNum = frame;
break;
}
case SET_JPG_PARTIAL_LINE_NUM: {
int line;
line = *(int *)param;
pEncInfo->partiallineNum = line;
break;
}
case SET_JPG_ENCODE_NEXT_LINE: {
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PARTIAL));
break;
}
case SET_JPG_USE_STUFFING_BYTE_FF: {
int enable;
enable = *(int *)param;
pEncInfo->stuffByteEnable = enable;
break;
}
case ENABLE_LOGGING: {
pJpgInst->loggingEnable = 1;
break;
}
case DISABLE_LOGGING: {
pJpgInst->loggingEnable = 0;
break;
}
default:
return JPG_RET_INVALID_COMMAND;
}
return JPG_RET_SUCCESS;
}