| /* |
| * 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); |
| } |