📄 dma.c
字号:
frame->list->tail = frame;
}
static frame_t *frame_take()
{
frame_t *frame;
frame = current_frame_list->head;
if (frame == NULL)
return NULL;
/* to keep DMA running
* the last frame should not be removed
*/
if (frame->next == NULL)
return NULL;
frame_clean_cache(frame);
if (frame_check_mark(frame))
return NULL;
current_frame_list->head = frame->next;
return frame;
}
static frame_t* alloc_frame(frame_list_t *list)
{
frame_t *frame;
frame = malloc(sizeof(frame_t));
if (frame == NULL)
return FALSE;
memset(frame, 0, sizeof(frame_t));
frame->list = list;
if (!frame_alloc_dma_buf(frame))
goto err_alloc_frame;
return frame;
err_alloc_frame:
free_frame(frame);
return NULL;
}
static void free_frame(frame_t* frame)
{
frame_free_dma_buf(frame);
free(frame);
}
static void free_frame_list(frame_list_t* list)
{
frame_t* i;
frame_t* next;
for (i = list->head; i; i = next)
{
next = i->next;
free_frame(i);
}
}
#define N_STILL_FRAMES 1
#define N_VIDEO_FRAMES 4
static BOOL alloc_frame_list(frame_list_t *list)
{
int i;
int n;
if (list->format.is_still)
n = N_STILL_FRAMES;
else
n = N_VIDEO_FRAMES;
for (i = 0; i < n; i++)
{
frame_t* tmp = alloc_frame(list);
if (!tmp)
{
free_frame_list(list);
return FALSE;
}
frame_append(tmp);
}
return TRUE;
}
#define MAX_FRAM_LIST 20
frame_list_t frame_list_tbl[MAX_FRAM_LIST];
UINT32 n_frame_list = 0;
BOOL QCIDMAPrepareFormat(format_t* format)
{
frame_list_t *list = find_frame_list(format);
if (list)
return TRUE;
memset(&frame_list_tbl[n_frame_list], 0, sizeof(frame_list_t));
memcpy(&frame_list_tbl[n_frame_list].format, format, sizeof(*format));
alloc_frame_list(&frame_list_tbl[n_frame_list]);
if (frame_list_tbl[n_frame_list].head != NULL)
{
if (!video_frame_tail && !format->is_still)
video_frame_tail = frame_list_tbl[n_frame_list].tail;
n_frame_list++;
return TRUE;
}
memset(&frame_list_tbl[n_frame_list], 0, sizeof(frame_list_t));
return FALSE;
}
static frame_list_t* find_frame_list(format_t* format)
{
UINT32 i;
for (i = 0; i < n_frame_list; i++)
{
frame_list_t* list = &frame_list_tbl[i];
if (!list->head)
continue;
if (memcmp(&list->format, format, sizeof(format_t)) == 0)
return list;
}
return NULL;
}
BOOL QCIDMASetFrameFormat(format_t* format)
{
current_frame_list = find_frame_list(format);
return current_frame_list != NULL;
}
void DMALoad()
{
int i;
frame_t* f;
if (!current_frame_list)
return;
if (!current_frame_list->head)
return;
for (f = current_frame_list->head; f; f = f->next)
{
frame_mark(f);
frame_clean_cache(f);
}
for (i = 0; i < 3; i++)
PXA_CIDMALoadDescriptor(g_pCIRegs,
current_frame_list->head->plane[i].desc_buf.phy_addr,
PXA_CI_DMA_CHANNEL_0 + i);
}
#ifdef DEBUG
static void dump_dma_chain(plane_t *plane)
{
UINT32 i;
PXA_CI_DMAC_DESCRIPTOR_T *descs;
UINT32 descs_n;
descs = (PXA_CI_DMAC_DESCRIPTOR_T*)plane->desc_buf.buf;
descs_n = plane->desc_buf.size / sizeof(*descs);
for (i = 0; i < descs_n; i++)
{
DEBUGMSG(ZONE_IOCTL,(L"CAM: %d ddadr 0x%08x, dsadr 0x%08x, dtadr 0x%08x, dcmd 0x%08x\r\n",
i, descs[i].ddadr, descs[i].dsadr, descs[i].dtadr, descs[i].dcmd));
}
}
static void dump_frame(frame_t *frame)
{
int i;
short *buf;
DEBUGMSG(ZONE_IOCTL,(L"CAM: Dumping frame 0x%08x\r\n",frame));
if (!frame)
return;
for (i = 0; i < 3; i++)
{
DEBUGMSG(ZONE_IOCTL,(L"CAM: descriptor 0x%08x, phyiscal address 0x%08x\r\n",
frame->plane[i].desc_buf.buf,
frame->plane[i].desc_buf.phy_addr));
dump_dma_chain(&frame->plane[i]);
}
for (i = 0; i < 10; i++)
DEBUGMSG(ZONE_IOCTL,(L"0x%02x ",frame->plane[0].buf.buf[i]));
DEBUGMSG(ZONE_IOCTL,(L"CAM: dumping frame mark\r\n"));
buf = (short*)get_mark_ptr(frame);
for (i = 0; i < 4; i++)
DEBUGMSG(ZONE_IOCTL,(L"CAM: 0x%04x \r\n",buf[i]));
}
void dump_frame_list(frame_list_t *frame_list)
{
frame_t *i;
DEBUGMSG(ZONE_IOCTL,(L"CAM: format %d\r\n", frame_list->format.format));
DEBUGMSG(ZONE_IOCTL,(L"CAM: width %d\r\n", frame_list->format.width));
DEBUGMSG(ZONE_IOCTL,(L"CAM: height %d\r\n", frame_list->format.height));
DEBUGMSG(ZONE_IOCTL,(L"CAM: head 0x%08x\r\n", frame_list->head));
DEBUGMSG(ZONE_IOCTL,(L"CAM: tail 0x%08x\r\n", frame_list->tail));
for (i = frame_list->head; i; i = i->next)
dump_frame(i);
}
#endif
DWORD WINAPI QciIntrThread()
{
int prio = 0;
#define MAX_READY_FRAME 10
frame_t *frames[MAX_READY_FRAME];
int n = 0;
int i;
prio = CeGetThreadPriority(GetCurrentThread());
while(1)
{
int status;
//void qci_dump_regs();
format_t* format;
status = WaitForSingleObject(qci_intr_event, INFINITE);
DEBUGMSG( ZONE_IOCTL, ( _T("CAM: Receive a complete frame!\r\n")));
if (status == WAIT_FAILED)
ERRORMSG(1, ( _T("CAM: QciIntrThread: WAIT_FAILED!!!\r\n")));
if (current_frame_list == NULL)
{
ERRORMSG(1, ( _T("CAM: Error no DMA frames!!!\r\n")));
continue;
}
format = ¤t_frame_list->format;
if (format->is_still)
{
#if 0
if (still_skips)
{
DEBUGMSG( ZONE_IOCTL, ( _T("CAM: Still capture shoule skip %d frames!\r\n"),still_skips));
still_skips--;
} else
#endif
{
DEBUGMSG( ZONE_IOCTL, ( _T("CAM: Receive a still frame!\r\n")));
QciCallBack(current_frame_list->head);
}
PXA_CIClearInterruptStatus(g_pCIRegs, 0xFFFFFFFF);
InterruptDone(qci_sys_intr);
continue;
}
n = 0;
while (1)
{
frames[n] = frame_take();
if (!frames[n])
break;
n++;
if (n >= MAX_READY_FRAME)
break;
}
if ((n>0)&&(frames[n-1]))//queue the last frame to callback function
QciCallBack(frames[n-1]);
for (i = 0; i < n; i++)
{
//QciCallBack(frames[i]);
frame_append(frames[i]);
}
PXA_CIClearInterruptStatus(g_pCIRegs, 0xFFFFFFFF);
InterruptDone(qci_sys_intr);
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -