blob: 39fc14ca2717e9c542ee76ece8caac1560006d46 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) Marvell International Ltd. and its affiliates
*
* Marvell GPL License Option
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
********************************************************************************/
#define _VPP_ISR_C_
#include "string.h"
#include "thinvpp.h"
#include "vpp_fe_dlr.h"
#include "api_avio_dhub.h"
#include "avioDhub.h"
#include "bcm_cmdi.h"
/////////////////////////////////////////////////////
//
// Interrupt Service Routines for FastLogo
//
/////////////////////////////////////////////////////
static void set_bcm_cmd(THINVPP_OBJ *vpp_obj, const unsigned * cmd, unsigned bytes)
{
BCMBUF *pbcmbuf = vpp_obj->pVbiBcmBuf;
memcpy(pbcmbuf->writer, cmd, bytes);
pbcmbuf->writer += (bytes/sizeof(*pbcmbuf->writer));
}
static void set_dma_cmd(THINVPP_OBJ *vpp_obj, PLANE *plane)
{
VBUF_INFO *pinfo = plane->pinfo;
unsigned frame_addr = (unsigned) pinfo->m_pbuf_start + (unsigned) pinfo->m_disp_offset;
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ->len += START_2DDMA(plane->dmaRdhubID, plane->dmaRID,
frame_addr, pinfo->m_buf_stride, plane->wpl*8, plane->actv_win.height,
(unsigned int (*)[2])(vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ->addr
+ vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ->len*2));
}
static void set_bcm_loader(THINVPP_OBJ *vpp_obj)
{
/* start read-back data loader */
*vpp_obj->pVbiBcmBuf->writer++ = 1;
*vpp_obj->pVbiBcmBuf->writer++ = 0xf7f70420;
}
static unsigned *m_Set80000000(unsigned *cmd, unsigned alpha, unsigned bgcolor)
{
cmd[0] = bgcolor&0xff;
cmd[2] = (bgcolor>>8)&0xff;
cmd[4] = (bgcolor>>16)&0xff;
cmd[6] = alpha&0xff;
cmd[8] = alpha&0xff;
return &cmd[10];
}
static unsigned *m_Set90000000(unsigned *cmd, unsigned hres, unsigned vres, unsigned CropWpl)
{
cmd[0] = (vres&0xffff) | (hres<<16);
cmd[2] = CropWpl;
return &cmd[4];
}
static unsigned *m_SetA0000000(unsigned *cmd, unsigned hres, unsigned vres)
{
cmd[0] = hres - 1;
cmd[2] = (vres/2) - 1;
cmd[4] = hres + 22 - 1;
cmd[6] = vres + 10 - 1;
cmd[8] = vres + 10 - 1;
cmd[10] = 1;
return &cmd[12];
}
static unsigned *m_SetB0000000(unsigned *cmd, unsigned hres, unsigned vres)
{
cmd[0] = (vres + 10) + ((hres + 20) << 16);
cmd[2] = (hres + 8) + (7 << 16);
cmd[4] = (vres + 3) + (2 << 16);
return &cmd[6];
}
static unsigned *m_SetC0000000(unsigned *cmd, unsigned hres, unsigned vres)
{
unsigned pix;
pix = hres * vres;
cmd[0] = pix;
cmd[2] = pix;
pix += hres;
cmd[4] = pix;
cmd[6] = (pix * 26 + 63)/64;
return &cmd[8];
}
static unsigned *m_SetD0000000(unsigned *cmd, unsigned x, unsigned y, unsigned w, unsigned h)
{
w += x;
h += y;
cmd[0] = x & 0xff;
cmd[2] = (x>>8) & 0xff;
cmd[4] = w & 0xff;
cmd[6] = (w>>8) & 0xff;
cmd[8] = y & 0xff;
cmd[10] = (y>>8) & 0xff;
cmd[12] = h & 0xff;
cmd[14] = (h>>8) & 0xff;
return &cmd[16];
}
static void init_bcm_cmd(THINVPP_OBJ *vpp_obj, unsigned * Cmd, unsigned bytes)
{
PLANE *plane = &vpp_obj->plane[PLANE_MAIN];
unsigned *CmdEnd = &Cmd[bytes/(sizeof(unsigned))];
VBUF_INFO * pinfo;
unsigned active_left, active_width;
unsigned CropWpl;
pinfo = plane->pinfo;
vpp_obj->chan[CHAN_MAIN].disp_win_attr.bgcolor = pinfo->bgcolor;
vpp_obj->chan[CHAN_MAIN].disp_win_attr.alpha = pinfo->alpha;
active_left = (pinfo->m_active_left) & ~1; //has to be even num
active_width = ((pinfo->m_active_left + pinfo->m_active_width) & ~1) - active_left; //has to be even num
plane->actv_win.x = active_left;
plane->actv_win.y = pinfo->m_active_top;
plane->actv_win.width = active_width;
plane->actv_win.height = pinfo->m_active_height;
CropWpl = (((plane->actv_win.width + PIXEL_PER_BEAT_YUV_422 - 1) / PIXEL_PER_BEAT_YUV_422) << 16);
plane->wpl = (CropWpl >> 16);
while (Cmd < CmdEnd)
{
switch (*Cmd)
{
case 0x80000000:
Cmd = m_Set80000000(Cmd, pinfo->alpha, pinfo->bgcolor);
break;
case 0x90000000:
Cmd = m_Set90000000(Cmd, pinfo->m_active_width, pinfo->m_active_height, CropWpl);
break;
case 0xa0000000:
Cmd = m_SetA0000000(Cmd, pinfo->m_active_width, pinfo->m_active_height);
break;
case 0xb0000000:
Cmd = m_SetB0000000(Cmd, pinfo->m_active_width, pinfo->m_active_height);
break;
case 0xc0000000:
Cmd = m_SetC0000000(Cmd, pinfo->m_active_width, pinfo->m_active_height);
break;
case 0xd0000000:
Cmd = m_SetD0000000(Cmd, pinfo->m_active_left, pinfo->m_active_top,
pinfo->m_active_width, pinfo->m_active_height);
break;
default:
Cmd += 2;
break;
}
}
}
static int startChannelDataLoader(THINVPP_OBJ *vpp_obj, int chanID)
{
if (chanID == CHAN_MAIN)
{
PLANE *plane = &vpp_obj->plane[PLANE_MAIN];
switch (plane->status) {
case STATUS_ACTIVE:
set_bcm_cmd(vpp_obj, cmd_startChannelDataLoader_active, sizeof(cmd_startChannelDataLoader_active));
plane->mode = MODE_INLINE;
set_dma_cmd(vpp_obj, plane);
set_bcm_loader(vpp_obj);
plane->status = STATUS_DISP;
break;
case STATUS_DISP:
set_dma_cmd(vpp_obj, plane);
set_bcm_loader(vpp_obj);
break;
case STATUS_STOP:
set_bcm_cmd(vpp_obj, cmd_startChannelDataLoader_stop, sizeof(cmd_startChannelDataLoader_stop));
plane->status = STATUS_INACTIVE;
break;
default:
break;
}
}
return (MV_THINVPP_OK);
}
static void prepareQ(THINVPP_OBJ *vpp_obj)
{
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ->len = 0;
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ->len = 0;
vpp_obj->pVbiBcmBuf = vpp_obj->pVbiBcmBufCpcb[CPCB_1];
THINVPP_BCMBUF_Select(vpp_obj->pVbiBcmBuf, CPCB_1);
}
static void toggleQ(THINVPP_OBJ *vpp_obj)
{
THINVPP_CFGQ_To_CFGQ(vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ, vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ);
THINVPP_BCMBUF_To_CFGQ(vpp_obj->pVbiBcmBuf, vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ);
THINVPP_BCMDHUB_CFGQ_Commit(vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ, CPCB_1);
if (vpp_obj->pVbiBcmBufCpcb[CPCB_1] == &vpp_obj->vbi_bcm_buf[0])
vpp_obj->pVbiBcmBufCpcb[CPCB_1] = &vpp_obj->vbi_bcm_buf[1];
else
vpp_obj->pVbiBcmBufCpcb[CPCB_1] = &vpp_obj->vbi_bcm_buf[0];
if (vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ == &vpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ = &(vpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1]);
else
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ = &(vpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0]);
if (vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ == &vpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0])
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ = &(vpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[1]);
else
vpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ = &(vpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0]);
}
/* interrupt service routine for CPCB TG interrupt */
void THINVPP_CPCB_ISR_service(THINVPP_OBJ *vpp_obj, int cpcbID)
{
DV *pDV;
if (!vpp_obj || (cpcbID != CPCB_1))
return;
pDV = &(vpp_obj->dv[cpcbID]);
if(pDV->status == STATUS_ACTIVE){
prepareQ(vpp_obj);
pDV->vbi_num ++; // VBI counter
startChannelDataLoader(vpp_obj, CHAN_MAIN);
toggleQ(vpp_obj);
} else if (pDV->status == STATUS_STOP) {
prepareQ(vpp_obj);
vpp_obj->dv[CPCB_1].vbi_num = 0; // reset VBI counter
vpp_obj->dv[CPCB_1].status = STATUS_INACTIVE;
toggleQ(vpp_obj);
}
}
void THINVPP_Enable_ISR_Interrupt(THINVPP_OBJ *vpp_obj, int cpcbID, int flag)
{
if (cpcbID != CPCB_1)
return;
if (flag) {
flag = 1;
init_bcm_cmd(vpp_obj, cmd_startChannelDataLoader_active, sizeof(cmd_startChannelDataLoader_active));
}
/* configure and enable CPCB0 interrupt */
semaphore_cfg(vpp_obj->pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr, 1, 0);
semaphore_pop(vpp_obj->pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr, 1);
semaphore_clr_full(vpp_obj->pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr);
semaphore_intr_enable(vpp_obj->pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr,
0/*empty*/, flag/*full*/, 0/*almost empty*/, 0/*almost full*/, 0/*cpu id*/);
}