blob: 90c98402ccb7c88eb15a58541f29db3f635c16a2 [file] [log] [blame]
/*
* Copyright (C) 2018 Synaptics Incorporated. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND
* SYNAPTICS EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE, AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY
* INTELLECTUAL PROPERTY RIGHTS. IN NO EVENT SHALL SYNAPTICS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, OR
* CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE
* OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED AND
* BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF
* COMPETENT JURISDICTION DOES NOT PERMIT THE DISCLAIMER OF DIRECT
* DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' TOTAL CUMULATIVE LIABILITY
* TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. DOLLARS.
*/
#define _VPP_ISR_C_
#include "vpp_module.h"
#include "vpp_cfg.h"
#include "vpp_bcmbuf.h"
#include "api_avio_dhub.h"
#include "vpp_api.h"
#include "io.h"
#include "show_logoframe.h"
#include "vpp_bcm_cmds_isr.h"
#include <common.h>
#define avioDhubSemMap_vpp_vppCPCB0_intr avioDhubSemMap_vpp128b_vpp_inr0
#define avioDhubSemMap_vpp_vppOUT4_intr avioDhubSemMap_vpp128b_vpp_inr6
#define bTST(x, b) (((x) >> (b)) & 1)
#define VPP_BCMBUF_WRITE(a, d) VPP_BCMBUF_Write(vpp_obj->pVbiBcmBuf, a, d)
#define VPP_BCMBUF_WRITE_CLEARBUF(a, d) \
VPP_BCMBUF_Write(vpp_obj->pVbiClearBcmBuf, a, d)
static VOID VPP_CPCB_ISR_service(VPP_OBJ *vpp_obj);
static VOID disp_callback_dummy(VOID *param);
voidfunc_t disp_isr_service = disp_callback_dummy;
voidfunc_t disp_after_isr_service = disp_callback_dummy;
voidfunc_t disp_dsr_service = disp_callback_dummy;
static VOID disp_callback_dummy(VOID *param)
{
(void)param;
}
VOID VPP_RegisterInterruptService(voidfunc_t f1, voidfunc_t f2, voidfunc_t f3)
{
if (NULL != f1)
disp_isr_service = f1;
if (NULL != f2)
disp_after_isr_service = f2;
if (NULL != f3)
disp_dsr_service = f3;
return;
}
void VPP_Enable_ISR_Interrupt(VPP_OBJ *vpp_obj, int cpcbID)
{
vpp_obj->pSemHandle = dhub_semaphore(&VPP_dhubHandle.dhub);
if (cpcbID == CPCB_1) {
/* configure and enable CPCB0 interrupt */
semaphore_cfg(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppCPCB0_intr,
1, 0);
semaphore_clr_full(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppCPCB0_intr);
semaphore_intr_enable(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppCPCB0_intr, 0,
1, 0, 0, 0);
semaphore_cfg(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppOUT4_intr,
1, 0);
semaphore_clr_full(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppOUT4_intr);
semaphore_intr_enable(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppOUT4_intr, 0,
1, 0, 0, 0);
}
}
void VPP_Disable_ISR_Interrupt(VPP_OBJ *vpp_obj, int cpcbID)
{
vpp_obj->pSemHandle = dhub_semaphore(&VPP_dhubHandle.dhub);
if (cpcbID == CPCB_1) {
semaphore_clr_full(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppCPCB0_intr);
semaphore_intr_enable(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppCPCB0_intr, 0,
0, 0, 0, 0);
semaphore_clr_full(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppOUT4_intr);
semaphore_intr_enable(vpp_obj->pSemHandle,
avioDhubSemMap_vpp_vppOUT4_intr, 0,
0, 0, 0, 0);
}
return;
}
static void updateFEChannelCurrentFrame(VPP_OBJ *vpp_obj)
{
VBUF_INFO *pinfo;
if (vpp_obj->dvstatus == STATUS_DISP_VIDEO) {
/* recycle only when new frame is popped */
if (vpp_obj->prev_curr_frame != vpp_obj->curr_frame &&
vpp_obj->prev_curr_frame)
frmq_push(&vpp_obj->outputq, vpp_obj->prev_curr_frame);
vpp_obj->prev_curr_frame = vpp_obj->curr_frame;
vpp_obj->curr_frame = NULL;
/* try to get a new frame descriptor from frame queue */
while (frmq_pop(&vpp_obj->inputq, (void **)&pinfo)) {
frmq_pop_commit(&vpp_obj->inputq);
/* recycle current frame descriptor */
if (vpp_obj->curr_frame) {
frmq_push(&vpp_obj->outputq,
vpp_obj->curr_frame);
}
vpp_obj->curr_frame = pinfo;
}
/*repeat the old frame if no one is not popped*/
if (!vpp_obj->curr_frame)
vpp_obj->curr_frame = vpp_obj->prev_curr_frame;
vpp_obj->frm_count++;
}
}
static int startChannelDataLoader(VPP_OBJ *vpp_obj)
{
VBUF_INFO *pinfo;
UINT32 *cfgQ, *cfgQ_shadow;
UINT32 *cfgQ_len;
cfgQ_shadow = vpp_obj->curr_cpcb_vbi_dma_cfgQ->addr;
cfgQ_len = &(vpp_obj->curr_cpcb_vbi_dma_cfgQ->len);
if (vpp_obj->dvstatus == STATUS_DISP_VIDEO)
pinfo = vpp_obj->curr_frame;
else
return MV_VPP_OK;
if (pinfo == NULL)
return MV_VPP_OK;
cfgQ = cfgQ_shadow + *cfgQ_len * 2;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
*cfgQ_len += START_2NDDMA(&VPP_dhubHandle, vpp_obj->dmaRID,
(UINT32)pinfo->m_pbuf_start,
pinfo->m_buf_stride, pinfo->m_buf_stride, 1,
pinfo->m_buf_stride, pinfo->m_active_height, (T64b *) cfgQ);
#pragma GCC diagnostic pop
return MV_VPP_OK;
}
int VPP_ISR_Handler(UINT32 msg_id, UINT32 msg_para, VPP_OBJ *vpp_obj)
{
int instat;
HRESULT rc;
unsigned int EmptySts;
if (vpp_obj->status != STATUS_ACTIVE)
return 0;
if (VPP_CC_MSG_TYPE_VPP == msg_id) {
instat = msg_para;
/* CPCB-0 VBI interrupt */
if (bTST(instat, avioDhubSemMap_vpp_vppCPCB0_intr)) {
BCM_SCHED_GetEmptySts(0, &EmptySts);
if (EmptySts == 0) {
vpp_obj->skip_vde_int = 1;
return 0;
} else {
vpp_obj->skip_vde_int = 0;
}
disp_dsr_service((void *)vpp_obj);
/* current VBI BCM cfgQ */
vpp_obj->curr_vbi_bcm_cfgQ =
vpp_obj->curr_cpcb_vbi_bcm_cfgQ;
/* reset vbi bcm & dma cfgQ length */
vpp_obj->curr_cpcb_vbi_bcm_cfgQ->len = 0;
vpp_obj->curr_cpcb_vbi_dma_cfgQ->len = 0;
/* select BCM buffer for the CPCB */
vpp_obj->pVbiBcmBuf =
vpp_obj->pVbiBcmBufCpcb[CPCB_1];
/* select BCM sub-buffer to dump register settings */
VPP_BCMBUF_Select(vpp_obj->pVbiBcmBuf, CPCB_1);
/* select CLEAR BCM buffer for the CPCB */
vpp_obj->pVbiClearBcmBuf =
vpp_obj->pVbiClearBcmBufCpcb[CPCB_1];
VPP_BCMBUF_Select(vpp_obj->pVbiClearBcmBuf, CPCB_1);
disp_isr_service(vpp_obj);
VPP_CPCB_ISR_service(vpp_obj);
/* generate CPCB-0 CLEAR BCM DHUB cmdQ and,*/
rc = VPP_BCMBUF_To_CFGQ(vpp_obj->pVbiClearBcmBuf,
vpp_obj->curr_vbi_bcm_cfgQ);
if (rc == MV_VPP_OK) {
if (vpp_obj->pVbiClearBcmBufCpcb[CPCB_1] ==
&vpp_obj->vbi_clear_bcm_buf[0])
vpp_obj->pVbiClearBcmBufCpcb[CPCB_1] =
&vpp_obj->vbi_clear_bcm_buf[1];
else
vpp_obj->pVbiClearBcmBufCpcb[CPCB_1] =
&vpp_obj->vbi_clear_bcm_buf[0];
}
/* generate CPCB-0 BCM DHUB cmdQ and,*/
rc = VPP_BCMBUF_To_CFGQ(vpp_obj->pVbiBcmBuf,
vpp_obj->curr_vbi_bcm_cfgQ);
VPP_CFGQ_To_CFGQ(vpp_obj->curr_cpcb_vbi_dma_cfgQ,
vpp_obj->curr_vbi_bcm_cfgQ);
if (rc == MV_VPP_OK) {
/* switch BCM buffer for the CPCB */
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];
}
rc = VPP_BCMDHUB_CFGQ_Commit(vpp_obj->curr_vbi_bcm_cfgQ,
CPCB_1, 0);
if (vpp_obj->curr_cpcb_vbi_dma_cfgQ ==
&vpp_obj->vbi_dma_cfgQ[0])
vpp_obj->curr_cpcb_vbi_dma_cfgQ =
&(vpp_obj->vbi_dma_cfgQ[1]);
else
vpp_obj->curr_cpcb_vbi_dma_cfgQ =
&(vpp_obj->vbi_dma_cfgQ[0]);
if (vpp_obj->curr_cpcb_vbi_bcm_cfgQ ==
&vpp_obj->vbi_bcm_cfgQ[0])
vpp_obj->curr_cpcb_vbi_bcm_cfgQ =
&(vpp_obj->vbi_bcm_cfgQ[1]);
else
vpp_obj->curr_cpcb_vbi_bcm_cfgQ =
&(vpp_obj->vbi_bcm_cfgQ[0]);
}
}
return MV_VPP_OK;
}
void VPP_CPCB_ISR_service(VPP_OBJ *vpp_obj)
{
static unsigned int x = 0;
static unsigned int y = 0;
static unsigned int w = 0;
static unsigned int h = 0;
unsigned int main_TG_PL_X, main_TG_PL_Y;
unsigned int crop_TG_PL_X, crop_TG_PL_Y, total_pixels;
unsigned int dlr_plane_size, dlr_client_size;
static int first_time_init = 1;
static VBUF_INFO *pinfo;
#ifdef BOOTLOGO_ANIM
static int ix = 0, iy = 0;
#endif
vpp_obj->vbi_num++;
if ((vpp_obj->dvstatus == STATUS_INACTIVE) ||
(vpp_obj->vbi_num <= 2))
return;
if (vpp_obj->dvstatus != STATUS_INACTIVE) {
if(frmq_pop(&vpp_obj->inputq, (void **)&pinfo))
{
x = pinfo->m_active_left;
y = pinfo->m_active_top;
w = pinfo->m_active_width;
h = pinfo->m_active_height;
}
#ifdef BOOTLOGO_ANIM
ix += 2;
iy += 2;
if((ix + pinfo->m_active_width) > MV_SYSTEM_XRES ||
(iy + pinfo->m_active_height) > MV_SYSTEM_YRES)
{
ix = 0;
iy = 0;
}
x = ix;
y = iy;
#endif
main_TG_PL_X = ((x & 0x1fff) | (((x+w) << 13) & 0x3ffe000));
main_TG_PL_Y = ((y & 0xfff) | (((y+h) << 12) & 0xfff000));
crop_TG_PL_X = ((x & 0x1fff) | (((x+w) << 13) & 0x3ffe000));
crop_TG_PL_Y = ((y & 0xfff) | (((y+h) << 12) & 0xfff000));
total_pixels = w * h;
dlr_plane_size = w * h;
dlr_client_size = ((((w+(w%8)) * 16 + 127) / 128) * h);
if(first_time_init == 1)
{
cmd_ISR_PRE_DL_1[82] = dlr_plane_size;
cmd_ISR_PRE_DL_1[94] = dlr_client_size;
cmd_ISR_PRE_DL_1[692] = main_TG_PL_X;
cmd_ISR_PRE_DL_1[694] = main_TG_PL_Y;
cmd_ISR_PRE_DL_1[696] = crop_TG_PL_X;
cmd_ISR_PRE_DL_1[698] = crop_TG_PL_Y;
cmd_ISR_PRE_DL_1[700] = total_pixels;
cmd_ISR_PRE_DL_1[702] = main_TG_PL_X;
cmd_ISR_PRE_DL_1[704] = main_TG_PL_Y;
VPP_BCMBUF_WriteBlock(vpp_obj->pVbiBcmBuf, cmd_ISR_PRE_DL_1, sizeof(cmd_ISR_PRE_DL_1));
}
else
{
cmd_ISR_PRE_DL_2[0] = dlr_plane_size;
cmd_ISR_PRE_DL_2[2] = dlr_client_size;
cmd_ISR_PRE_DL_2[4] = main_TG_PL_X;
cmd_ISR_PRE_DL_2[6] = main_TG_PL_Y;
cmd_ISR_PRE_DL_2[8] = crop_TG_PL_X;
cmd_ISR_PRE_DL_2[10] = crop_TG_PL_Y;
cmd_ISR_PRE_DL_2[12] = total_pixels;
cmd_ISR_PRE_DL_2[14] = main_TG_PL_X;
cmd_ISR_PRE_DL_2[16] = main_TG_PL_Y;
VPP_BCMBUF_WriteBlock(vpp_obj->pVbiBcmBuf, cmd_ISR_PRE_DL_2, sizeof(cmd_ISR_PRE_DL_2));
}
updateFEChannelCurrentFrame(vpp_obj);
startChannelDataLoader(vpp_obj);
if(first_time_init == 1)
{
VPP_BCMBUF_WriteBlock(vpp_obj->pVbiBcmBuf, cmd_ISR_PRE_DL_3, sizeof(cmd_ISR_PRE_DL_3));
}
else
{
VPP_BCMBUF_WriteBlock(vpp_obj->pVbiBcmBuf, cmd_ISR_PRE_DL_4, sizeof(cmd_ISR_PRE_DL_4));
}
}
first_time_init = 0;
return;
}
VOID MV_VPP_EnableISR(VPP_OBJ *pVpp_obj)
{
VPP_Enable_ISR_Interrupt(pVpp_obj, CPCB_1);
}
VOID MV_VPP_DisableISR(VPP_OBJ *pVpp_obj)
{
VPP_Disable_ISR_Interrupt(pVpp_obj, CPCB_1);
}