| /******************************************************************************* |
| * 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 _THINVPP_API_C_ |
| |
| #include "Galois_memmap.h" |
| #include "GaloisDmaMap.h" |
| #include "galois_io.h" |
| #include "global.h" |
| |
| #include "avpll.h" |
| #include "thinvpp.h" |
| #include "vpp_be_hdmitx.h" |
| #include "bcm_cmds.h" |
| #include "util.h" |
| #include "gpio.h" |
| |
| #define bTST(x, b) (((x) >> (b)) & 1) |
| |
| static int MV_THINVPP_SetHdmiVideoFmt(int color_fmt, int bit_depth, int pixel_rept); |
| void THINVPP_BCMBUF_HardwareTrans_Direct(int block, unsigned int *start, int size); |
| |
| unsigned MV_REG_GET(unsigned addr) |
| { |
| return *(volatile unsigned volatile *)(addr); |
| } |
| |
| void MV_REG_SET(unsigned addr, unsigned val) |
| { |
| *(volatile unsigned volatile *)(addr) = val; |
| } |
| |
| void MV_REG_AND(unsigned addr, unsigned val) |
| { |
| val = val & (*(volatile unsigned volatile *)(addr)); |
| *(volatile unsigned volatile *)(addr) = val; |
| } |
| |
| void MV_REG_ORR(unsigned addr, unsigned val) |
| { |
| val = val | (*(volatile unsigned volatile *)(addr)); |
| *(volatile unsigned volatile *)(addr) = val; |
| } |
| |
| void MV_REG_MASK(unsigned addr, unsigned mask, unsigned val) |
| { |
| val = (mask & (*(volatile unsigned volatile *)(addr))) | val; |
| *(volatile unsigned volatile *)(addr) = val; |
| } |
| |
| void delay_10ns(int delay) |
| { |
| int i; |
| |
| for (i=0; i<delay; i++) { |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| __asm__ __volatile__ ("MOV r0, r0" "\n\t" :::"r0"); |
| } |
| } |
| |
| static int GetVCOFreq(int resID, int bit_depth) |
| { |
| if (resID == RES_RESET) |
| return (-1); |
| |
| int avpll_freq_index, deep_color_index; |
| |
| if (m_resinfo_table[resID].freq <= 25200) { |
| avpll_freq_index = 0; |
| } else if ((m_resinfo_table[resID].freq == 27000) || (m_resinfo_table[resID].freq == 27027)) { |
| avpll_freq_index = 1; |
| } else if ((m_resinfo_table[resID].freq == 74250) || (m_resinfo_table[resID].freq == 74176)) { |
| avpll_freq_index = 3; |
| } else if ((m_resinfo_table[resID].freq == 148500) || (m_resinfo_table[resID].freq == 148352)) { |
| avpll_freq_index = 5; |
| } else |
| return (-1); |
| |
| if (bit_depth == OUTPUT_BIT_DEPTH_12BIT) |
| deep_color_index = 2; |
| else if (bit_depth == OUTPUT_BIT_DEPTH_10BIT) |
| deep_color_index = 1; |
| else if (bit_depth == OUTPUT_BIT_DEPTH_8BIT) |
| deep_color_index = 0; |
| else |
| return (-1); |
| |
| return (diag_getVCOFreq(deep_color_index, avpll_freq_index)); |
| } |
| |
| static int NeedAVPLL_PPM1K(int resID) |
| { |
| int frame_rate; |
| int ret; |
| |
| frame_rate = m_resinfo_table[resID].frame_rate; |
| if (m_resinfo_table[resID].type == TYPE_SD) { |
| /* for SD resolution */ |
| if ((frame_rate == FRAME_RATE_59P94) || (frame_rate == FRAME_RATE_50)) |
| ret = 0; |
| else |
| ret = 1; |
| } else { |
| /* for HD resolution */ |
| if ((frame_rate == FRAME_RATE_59P94) || (frame_rate == FRAME_RATE_29P97) || (frame_rate == FRAME_RATE_23P98) || (frame_rate == FRAME_RATE_119P88) || (frame_rate == FRAME_RATE_47P96)) |
| ret = 0; |
| else |
| ret = 1;; |
| } |
| |
| return ret; |
| } |
| |
| static void VPP_dhub_sem_clear(void) |
| { |
| int instat; |
| |
| HDL_semaphore *pSemHandle = thinvpp_obj->pSemHandle; |
| |
| instat = semaphore_chk_full(pSemHandle, -1); |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppCPCB0_intr)){ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr); |
| }else if (bTST(instat, avioDhubSemMap_vpp_vppCPCB2_intr)){ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppCPCB2_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppCPCB2_intr); |
| } |
| |
| return; |
| } |
| |
| |
| /*********************************************** |
| * FUNCTION: create a VPP object |
| * PARAMS: base_addr - VPP object base address |
| * *handle - pointer to object handle |
| * RETURN: MV_THINVPP_OK - succeed |
| * MV_THINVPP_EUNCONFIG - not initialized |
| ***********************************************/ |
| int MV_THINVPP_Create(int base_addr, unsigned options) |
| { |
| if (!(thinvpp_obj = (THINVPP_OBJ *)THINVPP_MALLOC(sizeof(THINVPP_OBJ)))){ |
| return (MV_THINVPP_ENOMEM); |
| } |
| |
| THINVPP_MEMSET(thinvpp_obj, 0, sizeof(THINVPP_OBJ)); |
| |
| thinvpp_obj->options = options; |
| thinvpp_obj->base_addr = base_addr; |
| |
| /* create VBI BCM buffer */ |
| if (THINVPP_BCMBUF_Create(&(thinvpp_obj->vbi_bcm_buf[0]), BCM_BUFFER_SIZE) != MV_THINVPP_OK){ |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| |
| if (thinvpp_obj->options & THINVPP_OPTION_SHOWLOGO) |
| { |
| if (THINVPP_BCMBUF_Create(&(thinvpp_obj->vbi_bcm_buf[1]), BCM_BUFFER_SIZE) != MV_THINVPP_OK){ |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| |
| |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[1]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[1])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[1]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_3].vbi_bcm_cfgQ[0]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[1])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| if (THINVPP_CFGQ_Create(&(thinvpp_obj->dv[CPCB_3].vbi_bcm_cfgQ[1]), DMA_CMD_BUFFER_SIZE) != MV_THINVPP_OK) { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_bcm_cfgQ[0])); |
| THINVPP_FREE(thinvpp_obj); |
| return (MV_THINVPP_ENOMEM); |
| } |
| } |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| /*********************************************** |
| * FUNCTION: destroy a VPP object |
| * PARAMS: handle - VPP object handle |
| * RETURN: MV_THINVPP_OK - succeed |
| * MV_THINVPP_EUNCONFIG - not initialized |
| * MV_THINVPP_ENODEV - no device |
| * MV_THINVPP_ENOMEM - no memory |
| ***********************************************/ |
| int MV_THINVPP_Destroy(void) |
| { |
| if (thinvpp_obj == NULL) |
| return (MV_THINVPP_ENODEV); |
| |
| /* free BCM buffer memory */ |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[0])); |
| if (thinvpp_obj->options & THINVPP_OPTION_SHOWLOGO) |
| { |
| THINVPP_BCMBUF_Destroy(&(thinvpp_obj->vbi_bcm_buf[1])); |
| |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[1])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_bcm_cfgQ[0])); |
| THINVPP_CFGQ_Destroy(&(thinvpp_obj->dv[CPCB_3].vbi_bcm_cfgQ[1])); |
| } |
| |
| /* free vpp object memory */ |
| THINVPP_FREE(thinvpp_obj); |
| thinvpp_obj = NULL; |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| /*************************************** |
| * FUNCTION: VPP reset |
| * INPUT: NONE |
| * RETURN: NONE |
| **************************************/ |
| int MV_THINVPP_Reset(void) |
| { |
| unsigned i; |
| unsigned reg; |
| (void)reg; |
| |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| // reset VPP object variable |
| thinvpp_obj->status = STATUS_INACTIVE; |
| |
| /* reset planes */ |
| for (i=FIRST_PLANE; i<MAX_NUM_PLANES; i++){ |
| thinvpp_obj->plane[i].status = STATUS_INACTIVE; |
| thinvpp_obj->plane[i].mode = -1; // invalid |
| thinvpp_obj->plane[i].srcfmt = -1; // invalid |
| thinvpp_obj->plane[i].order = -1; // invalid |
| |
| thinvpp_obj->plane[i].actv_win.x = 0; |
| thinvpp_obj->plane[i].actv_win.y = 0; |
| thinvpp_obj->plane[i].actv_win.width = 0; |
| thinvpp_obj->plane[i].actv_win.height = 0; |
| |
| thinvpp_obj->plane[i].ref_win = thinvpp_obj->plane[i].actv_win; |
| } |
| |
| /* reset channels */ |
| for (i=FIRST_CHAN; i<MAX_NUM_CHANS; i++) { |
| thinvpp_obj->chan[i].status = STATUS_INACTIVE; |
| thinvpp_obj->chan[i].dvID = -1; // invalid |
| thinvpp_obj->chan[i].dvlayerID = -1; // invalid |
| thinvpp_obj->chan[i].zorder = -1; // invalid |
| |
| thinvpp_obj->chan[i].disp_win.x = 0; |
| thinvpp_obj->chan[i].disp_win.y = 0; |
| thinvpp_obj->chan[i].disp_win.width = 0; |
| thinvpp_obj->chan[i].disp_win.height = 0; |
| } |
| |
| /* reset DVs */ |
| for (i=FIRST_CPCB; i<MAX_NUM_CPCBS; i++) { |
| thinvpp_obj->dv[i].status = STATUS_INACTIVE; |
| thinvpp_obj->dv[i].output_res = RES_INVALID; // invalid |
| thinvpp_obj->dv[i].num_of_vouts = 0; |
| thinvpp_obj->dv[i].vbi_num = 0; |
| } |
| |
| /* reset VOUTs */ |
| for (i=FIRST_VOUT; i<MAX_NUM_VOUTS; i++) { |
| thinvpp_obj->vout[i].status = STATUS_INACTIVE; |
| thinvpp_obj->vout[i].dvID = -1; // invalid |
| } |
| |
| /* reset VBI BCM buffer */ |
| THINVPP_BCMBUF_Reset(&thinvpp_obj->vbi_bcm_buf[0]); |
| thinvpp_obj->pVbiBcmBuf = &(thinvpp_obj->vbi_bcm_buf[0]); |
| if (thinvpp_obj->options & THINVPP_OPTION_SHOWLOGO) |
| { |
| THINVPP_BCMBUF_Reset(&thinvpp_obj->vbi_bcm_buf[1]); |
| thinvpp_obj->pVbiBcmBufCpcb[CPCB_1] = &(thinvpp_obj->vbi_bcm_buf[0]); |
| thinvpp_obj->pVbiBcmBufCpcb[CPCB_3] = &(thinvpp_obj->vbi_bcm_buf[0]); |
| |
| thinvpp_obj->dv[CPCB_1].curr_cpcb_vbi_dma_cfgQ = &(thinvpp_obj->dv[CPCB_1].vbi_dma_cfgQ[0]); |
| thinvpp_obj->dv[CPCB_3].curr_cpcb_vbi_dma_cfgQ = &(thinvpp_obj->dv[CPCB_3].vbi_dma_cfgQ[0]); |
| thinvpp_obj->dv[CPCB_1].curr_cpcb_vbi_bcm_cfgQ = &(thinvpp_obj->dv[CPCB_1].vbi_bcm_cfgQ[0]); |
| thinvpp_obj->dv[CPCB_3].curr_cpcb_vbi_bcm_cfgQ = &(thinvpp_obj->dv[CPCB_3].vbi_bcm_cfgQ[0]); |
| } |
| |
| /* reset dHub cmdQ */ |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) |
| for (i = 0; i < avioDhubChMap_vpp_TT_R; i++) |
| #else // (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) |
| for (i = 0; i < avioDhubChMap_vpp_SPDIF_W; i++) |
| #endif // (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) |
| thinvpp_obj->dhub_cmdQ[i] = 0; |
| |
| { |
| register unsigned reg = 0xf7f70068; |
| register unsigned val; |
| |
| SM_GPIO_PortWrite(1, 1); // set SM GPIO port 1 to high, this is input/output control of SM GPIO port 7 |
| |
| val = MV_REG_GET(reg); |
| if (0 != (val & 0x3c)) |
| { |
| // @bit 0, 13..10, 17..14, 18, 31..19 |
| val = (val & 0x1fe) | (8<<10) | (1<<18) | (0x924<<19); |
| MV_REG_SET(reg, val); |
| |
| // Set Aux |
| MV_REG_AND(reg + 0xc, ~(0xff<<9)); // @bit 16..9 |
| |
| // Set Eamp @bit 11..0, 27..12, 31..28 |
| val = MV_REG_GET(reg + 0x4); |
| val = 0x249 | (0x2222<<12) | (0x7<<28); |
| MV_REG_SET(reg + 0x4, val); |
| |
| // Set SVTX and IDRV @bit 11..0, 29..12 |
| val = MV_REG_GET(reg + 0x8); |
| val = (val & 0xc0000000) | (0xff<<12) | 0x249; |
| MV_REG_SET(reg + 0x8, val); |
| |
| // BE_HDMIPHY_EnableTmds: |
| MV_REG_AND(reg, ~0x3c); // @bit 5..2 |
| MV_REG_ORR(reg, 0x02); // @bit 1 |
| MV_REG_AND(reg, ~0x02); |
| } |
| |
| MV_REG_SET(0xf7f644c0, 0x01); // BE_HDMITX_EnablePhyFifo: |
| MV_REG_MASK(reg, ~(0xfff<<19), (0x492<<19)); // @bit 30..19 |
| MV_REG_MASK(reg + 4, ~0xfff, 0x249); // @bit 11..0 |
| } |
| |
| THINVPP_BCMBUF_HardwareTrans_Direct(1, cmd_THINVPP_Reset, sizeof(cmd_THINVPP_Reset)); |
| |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| /*************************************** |
| * FUNCTION: VPP profile configuration |
| * INPUT: NONE |
| * RETURN: NONE |
| **************************************/ |
| int MV_THINVPP_Config(void) |
| { |
| int i; |
| |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| /* VPP module has been configured */ |
| if (thinvpp_obj->status == STATUS_ACTIVE) |
| return (MV_THINVPP_OK); |
| |
| thinvpp_obj->pSemHandle = dhub_semaphore(&VPP_dhubHandle.dhub); |
| |
| /* config planes */ |
| for (i=FIRST_PLANE; i<MAX_NUM_PLANES; i++){ |
| |
| /* set plane's DMA channel ID */ |
| if (i == PLANE_MAIN){ |
| thinvpp_obj->plane[i].dmaRID = avioDhubChMap_vpp_MV_R; // inline read DMA |
| thinvpp_obj->plane[i].dmaRdhubID = (int)(&VPP_dhubHandle); |
| thinvpp_obj->plane[i].offline_dmaWID = avioDhubChMap_vpp_MV_FRC_W; // offline write-back DMA |
| thinvpp_obj->plane[i].offline_dmaWdhubID = (int)(&VPP_dhubHandle); |
| thinvpp_obj->plane[i].offline_dmaRID = avioDhubChMap_vpp_MV_FRC_R; // offline readd-back DMA |
| thinvpp_obj->plane[i].offline_dmaRdhubID = (int)(&VPP_dhubHandle); |
| break; |
| } |
| |
| } // <- config FE planes |
| |
| /* config channels */ |
| #if LOGO_ENABLE_MAIN |
| thinvpp_obj->chan[CHAN_MAIN].dvID = CPCB_1; //#if LOGO_ENABLE_MAIN |
| #endif |
| #if LOGO_ENABLE_PIP |
| thinvpp_obj->chan[CHAN_PIP].dvID = CPCB_1; |
| #endif |
| thinvpp_obj->chan[CHAN_AUX].dvID = CPCB_3; |
| |
| #if LOGO_ENABLE_MAIN |
| thinvpp_obj->chan[CHAN_MAIN].zorder = CPCB_ZORDER_7; //#if LOGO_ENABLE_MAIN |
| #endif |
| #if LOGO_ENABLE_PIP |
| thinvpp_obj->chan[CHAN_PIP].zorder = CPCB_ZORDER_2; |
| #endif |
| thinvpp_obj->chan[CHAN_AUX].zorder = CPCB_ZORDER_1; |
| |
| // for B0, channel connection with CPCB is fixed |
| #if LOGO_ENABLE_MAIN |
| thinvpp_obj->chan[CHAN_MAIN].dvlayerID = CPCB1_PLANE_1; //#if LOGO_ENABLE_MAIN |
| #endif |
| #if LOGO_ENABLE_PIP |
| thinvpp_obj->chan[CHAN_PIP].dvlayerID = CPCB1_PLANE_2; |
| #endif |
| thinvpp_obj->chan[CHAN_AUX].dvlayerID = CPCB1_PLANE_1; // PLANE-1 of CPCB-2 |
| |
| #if LOGO_ENABLE_MAIN |
| #if LOGO_ENABLE_PIP || ((BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) && (BERLIN_CHIP_VERSION != BERLIN_BG2CDP)) |
| thinvpp_obj->dv[CPCB_1].num_of_chans = 2; |
| thinvpp_obj->dv[CPCB_1].chanID[0] = CHAN_MAIN; |
| thinvpp_obj->dv[CPCB_1].chanID[1] = CHAN_PIP; |
| #else |
| thinvpp_obj->dv[CPCB_1].num_of_chans = 1; |
| thinvpp_obj->dv[CPCB_1].chanID[0] = CHAN_MAIN; |
| #endif |
| #else |
| #if LOGO_ENABLE_PIP |
| thinvpp_obj->dv[CPCB_1].num_of_chans = 1; |
| thinvpp_obj->dv[CPCB_1].chanID[0] = CHAN_PIP; |
| #else |
| thinvpp_obj->dv[CPCB_1].num_of_chans = 0; |
| #endif |
| #endif |
| thinvpp_obj->dv[CPCB_1].num_of_vouts = 2; |
| thinvpp_obj->dv[CPCB_1].voutID[0] = VOUT_HDMI; |
| thinvpp_obj->dv[CPCB_1].voutID[1] = VOUT_HD; |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) && (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| thinvpp_obj->dv[CPCB_3].num_of_chans = 1; |
| thinvpp_obj->dv[CPCB_3].chanID[0] = CHAN_AUX; |
| thinvpp_obj->dv[CPCB_3].num_of_vouts = 1; |
| thinvpp_obj->dv[CPCB_3].voutID[0] = VOUT_SD; |
| #else // (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) |
| thinvpp_obj->dv[CPCB_3].num_of_chans = 0; |
| #endif // (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) |
| |
| /* config VOUTs */ |
| thinvpp_obj->vout[VOUT_HDMI].dvID = CPCB_1; |
| thinvpp_obj->vout[VOUT_HD].dvID = CPCB_1; |
| thinvpp_obj->vout[VOUT_SD].dvID = CPCB_3; |
| |
| THINVPP_BCMBUF_HardwareTrans_Direct(1, cmd_THINVPP_Config, sizeof(cmd_THINVPP_Config)); |
| |
| if (thinvpp_obj->options & THINVPP_OPTION_SHOWLOGO) |
| { |
| BCM_SCHED_SetMux(BCM_SCHED_Q0, 0); /* CPCB0 VBI -> Q0 */ |
| BCM_SCHED_SetMux(BCM_SCHED_Q1, 1); /* CPCB1 VBI -> Q1 */ |
| BCM_SCHED_SetMux(BCM_SCHED_Q2, 2); /* CPCB2 VBI -> Q2 */ |
| BCM_SCHED_SetMux(BCM_SCHED_Q3, 3); /* CPCB0 VDE -> Q3 */ |
| BCM_SCHED_SetMux(BCM_SCHED_Q4, 4); /* CPCB1 VDE -> Q4 */ |
| BCM_SCHED_SetMux(BCM_SCHED_Q5, 5); /* CPCB2 VDE -> Q5 */ |
| } |
| |
| /* set VPP module to be configured */ |
| thinvpp_obj->status = STATUS_ACTIVE; |
| return (MV_THINVPP_OK); |
| } |
| |
| /******************************************************************* |
| * FUNCTION: set CPCB or DV output resolution |
| * INPUT: cpcbID - CPCB(for Berlin) or DV(for Galois) id |
| * resID - id of output resolution |
| * bit_depth - HDMI deep color bit depth |
| * RETURN: MV_THINVPP_OK - SUCCEED |
| * MV_EBADPARAM - invalid parameters |
| * MV_EUNCONFIG - VPP not configured or plane not active |
| * MV_EFRAMEQFULL - frame queue is full |
| * Note: this function has to be called before enabling a plane |
| * which belongs to that CPCB or DV. |
| *******************************************************************/ |
| int MV_THINVPP_SetCPCBOutputResolution(int cpcbID, int resID, int bit_depth) |
| { |
| int vco_freq; |
| int ppm1k_en; |
| int avpll_freq_index; |
| int deep_color_index; |
| float ovsmp_index; |
| (void)vco_freq; |
| |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| if (resID<FIRST_RES || resID>=MAX_NUM_RESS) |
| return (MV_THINVPP_EBADPARAM); |
| |
| if (thinvpp_obj->status == STATUS_INACTIVE){ |
| /* VPP module is not configured */ |
| return (MV_THINVPP_EUNCONFIG); |
| } |
| |
| if (cpcbID<FIRST_CPCB || cpcbID>=MAX_NUM_CPCBS) |
| return (MV_THINVPP_EBADPARAM); |
| |
| vco_freq = GetVCOFreq(resID, bit_depth); |
| |
| if (resID != RES_RESET) { |
| |
| /* set CPCB new resolution */ |
| if (m_resinfo_table[resID].freq <= 25200) { |
| avpll_freq_index = 0; |
| ovsmp_index = 4.0; |
| } else if ((m_resinfo_table[resID].freq == 27000) || (m_resinfo_table[resID].freq == 27027)) { |
| avpll_freq_index = 1; |
| ovsmp_index = 4.0; |
| } else if ((m_resinfo_table[resID].freq == 74250) || (m_resinfo_table[resID].freq == 74176)) { |
| avpll_freq_index = 3; |
| ovsmp_index = 2.0; |
| } else if ((m_resinfo_table[resID].freq == 148500) || (m_resinfo_table[resID].freq == 148352)) { |
| avpll_freq_index = 5; |
| ovsmp_index = 1.0; |
| } else { |
| return (MV_THINVPP_EBADPARAM); |
| } |
| |
| if (bit_depth == OUTPUT_BIT_DEPTH_12BIT) |
| deep_color_index = 2; |
| else if (bit_depth == OUTPUT_BIT_DEPTH_10BIT) |
| deep_color_index = 1; |
| else if (bit_depth == OUTPUT_BIT_DEPTH_8BIT) |
| deep_color_index = 0; |
| else |
| return (MV_THINVPP_EBADPARAM); |
| |
| ppm1k_en = NeedAVPLL_PPM1K(resID); |
| |
| if (cpcbID == CPCB_1) |
| diag_videoFreq_A(avpll_freq_index, deep_color_index, ppm1k_en, ovsmp_index, 6); |
| else if (cpcbID == CPCB_2) |
| diag_videoFreq_A(avpll_freq_index, deep_color_index, ppm1k_en, ovsmp_index, 5); |
| else if (cpcbID == CPCB_3) |
| diag_videoFreq_B(avpll_freq_index, 2 /* always set to 12-bit for AUX */, ppm1k_en, ovsmp_index, 6); |
| |
| delay_10ns(2000000); |
| |
| thinvpp_obj->dv[cpcbID].output_res = resID; |
| THINVPP_BCMBUF_HardwareTrans_Direct(1, cmd_THINVPP_SetCPCBOutputResolution, sizeof(cmd_THINVPP_SetCPCBOutputResolution)); |
| |
| if (cpcbID == CPCB_1) |
| MV_THINVPP_SetHdmiVideoFmt(OUTPUT_COLOR_FMT_RGB888, bit_depth, 1); |
| |
| /* set DV status to active */ |
| thinvpp_obj->dv[cpcbID].status = STATUS_ACTIVE; |
| } |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| int MV_THINVPP_IsCPCBActive(int cpcbID) |
| { |
| int vtotal; |
| |
| if (cpcbID == CPCB_1) { |
| vtotal = (GLB_REG_READ32(MEMMAP_VPP_REG_BASE+(CPCB0_VT_H << 2)) & 0x0ff); |
| vtotal <<= 8; |
| vtotal |= (GLB_REG_READ32(MEMMAP_VPP_REG_BASE+(CPCB0_VT_L << 2)) & 0x0ff); |
| } else if (cpcbID == CPCB_3) { |
| vtotal = (GLB_REG_READ32(MEMMAP_VPP_REG_BASE+(CPCB2_VT_H << 2)) & 0x0ff); |
| vtotal <<= 8; |
| vtotal |= (GLB_REG_READ32(MEMMAP_VPP_REG_BASE+(CPCB2_VT_L << 2)) & 0x0ff); |
| } else |
| vtotal = 0; |
| |
| return (vtotal); |
| } |
| |
| |
| |
| |
| int MV_THINVPP_SetMainRefWindow(const VPP_WIN *win) |
| { |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| if (!win) |
| return (MV_THINVPP_EBADPARAM); |
| |
| #if LOGO_ENABLE_MAIN |
| thinvpp_obj->plane[PLANE_MAIN].ref_win = *win; |
| #else |
| thinvpp_obj->plane[PLANE_PIP].ref_win = *win; |
| #endif |
| return (MV_THINVPP_OK); |
| } |
| |
| int MV_THINVPP_SetMainDisplayFrame(VBUF_INFO *pinfo) |
| { |
| PLANE *plane; |
| |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| if (!pinfo) |
| return (MV_THINVPP_EBADPARAM); |
| |
| #if LOGO_ENABLE_MAIN |
| plane = &(thinvpp_obj->plane[PLANE_MAIN]); |
| #else |
| plane = &(thinvpp_obj->plane[PLANE_PIP]); |
| #endif |
| plane->pinfo = pinfo; |
| |
| plane->actv_win.x = pinfo->m_active_left; |
| plane->actv_win.y = pinfo->m_active_top; |
| plane->actv_win.width = pinfo->m_active_width; |
| plane->actv_win.height = pinfo->m_active_height; |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| /****************************************************************************** |
| * FUNCTION: open a window of a video/graphics plane for display. |
| * the window is defined in end display resolution |
| * INPUT: planeID - id of a video/grahpics plane |
| * *win - pointer to a vpp window struct |
| * *attr - pointer to a vpp window attribute struct |
| * RETURN: MV_THINVPP_OK - SUCCEED |
| * MV_EBADPARAM - invalid parameters |
| * MV_EUNCONFIG - VPP not configured |
| * MV_EUNSUPPORT - plane not connected in configuration |
| * MV_ECMDQFULL - command queue is full |
| ******************************************************************************/ |
| int MV_THINVPP_OpenDispWindow(int planeID, const VPP_WIN *win, const VPP_WIN_ATTR *attr) |
| { |
| int chanID; |
| int cpcbID; |
| PLANE *plane; |
| CHAN *chan; |
| |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| if (planeID<FIRST_PLANE || planeID>=MAX_NUM_PLANES) |
| return (MV_THINVPP_EBADPARAM); |
| |
| if (!win) |
| return (MV_THINVPP_EBADPARAM); |
| |
| if ((win->width<=0) || (win->height<=0)) |
| return (MV_THINVPP_EBADPARAM); |
| |
| if (thinvpp_obj->status == STATUS_INACTIVE){ |
| /* VPP module is not configured */ |
| return (MV_THINVPP_EUNCONFIG); |
| } |
| |
| plane = &(thinvpp_obj->plane[planeID]); |
| chanID = planeID; |
| chan = &(thinvpp_obj->chan[chanID]); |
| cpcbID = chan->dvID; |
| |
| /* update video/graphics channel display window */ |
| chan->disp_win.x = win->x; |
| chan->disp_win.y = win->y; |
| chan->disp_win.width = win->width; |
| chan->disp_win.height = win->height; |
| |
| if (plane->ref_win.width == 0) |
| plane->ref_win.width = chan->disp_win.width; |
| if (plane->ref_win.height == 0) |
| plane->ref_win.height = chan->disp_win.height; |
| |
| if (attr){ |
| chan->disp_win_attr.bgcolor = attr->bgcolor; |
| chan->disp_win_attr.alpha = attr->alpha; |
| } else { |
| chan->disp_win_attr.bgcolor = DEFAULT_BGCOLOR; |
| chan->disp_win_attr.alpha = DEFAULT_ALPHA; |
| } |
| /* set video/graphics plane & channel in active status */ |
| plane->status = STATUS_ACTIVE; |
| chan->status = STATUS_ACTIVE; |
| THINVPP_Enable_ISR_Interrupt(thinvpp_obj, cpcbID, 1); |
| VPP_dhub_sem_clear(); |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| int MV_THINVPP_CloseDispWindow(void) |
| { |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| /* wait for CPCB TG reset done */ |
| thinvpp_obj->plane[PLANE_MAIN].status = STATUS_STOP; |
| thinvpp_obj->plane[PLANE_PIP].status = STATUS_STOP; |
| thinvpp_obj->plane[PLANE_AUX].status = STATUS_STOP; |
| |
| while(thinvpp_obj->plane[PLANE_MAIN].status != STATUS_INACTIVE); |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| int MV_THINVPP_Stop(void) |
| { |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| /* wait for CPCB TG reset done */ |
| MV_REG_AND(0xf7f70068, ~(0x0fff<<19)); // SET32HDMI_ctrl_DAMP(regData, 0); |
| MV_REG_AND(0xf7f70068 + 4, ~0x0fff); // SET32HDMI_ctrl_EAMP(regData, 0); |
| |
| thinvpp_obj->dv[CPCB_1].status = STATUS_STOP; |
| thinvpp_obj->dv[CPCB_3].status = STATUS_STOP; |
| // if (thinvpp_obj->plane[PLANE_MAIN].status != STATUS_INACTIVE) |
| while(thinvpp_obj->dv[CPCB_1].status != STATUS_INACTIVE); |
| |
| // disable CPCB VBI interrupts |
| THINVPP_Enable_ISR_Interrupt(thinvpp_obj, CPCB_1, 0); |
| THINVPP_Enable_ISR_Interrupt(thinvpp_obj, CPCB_3, 0); |
| VPP_dhub_sem_clear(); |
| |
| return (MV_THINVPP_OK); |
| } |
| |
| /******************************************************************************** |
| * FUNCTION: Set Hdmi Video format |
| * INPUT: color_fmt - color format (RGB, YCbCr 444, 422) |
| * : bit_depth - 8/10/12 bit color |
| * : pixel_rept - 1/2/4 repetitions of pixel |
| * RETURN: MV_THINVPP_OK - SUCCEED |
| * MV_EBADPARAM - invalid parameters |
| * MV_EUNCONFIG - VPP not configured |
| * MV_THINVPP_ENODEV - no device |
| * MV_EUNSUPPORT - channel not connected in configuration |
| * MV_THINVPP_EBADCALL - channel not connected to DV1 |
| * MV_ECMDQFULL - command queue is full |
| ********************************************************************************/ |
| int MV_THINVPP_SetHdmiVideoFmt(int color_fmt, int bit_depth, int pixel_rept) |
| { |
| int cpcbID; |
| int resID; |
| int instat; |
| int avpll_freq_index; |
| int deep_color_index; |
| float freq_factor; |
| int ppm1k_en; |
| (void)color_fmt; |
| |
| if (!thinvpp_obj) |
| return (MV_THINVPP_ENODEV); |
| |
| if ((cpcbID = CPCB_OF_VOUT(thinvpp_obj, VOUT_HDMI)) == CPCB_INVALID) { |
| /* Output is not connected to any DV in configuration */ |
| return (MV_THINVPP_EUNSUPPORT); |
| } |
| |
| /* Configure AVPLL */ |
| resID = thinvpp_obj->dv[cpcbID].output_res; |
| if (resID == RES_INVALID) |
| return (MV_THINVPP_EBADPARAM); |
| |
| if ((m_resinfo_table[resID].freq == 25200) || (m_resinfo_table[resID].freq == 25175)) { |
| avpll_freq_index = 0; |
| } else if ((m_resinfo_table[resID].freq == 27000) || (m_resinfo_table[resID].freq == 27027)) { |
| avpll_freq_index = 1; |
| if (pixel_rept == 2) { |
| if (m_resinfo_table[resID].scan != SCAN_INTERLACED) |
| avpll_freq_index = 2; |
| } else if (pixel_rept == 4) { |
| if (m_resinfo_table[resID].scan != SCAN_INTERLACED) |
| avpll_freq_index = 4; |
| else |
| avpll_freq_index = 2; |
| } |
| } else if ((m_resinfo_table[resID].freq == 74250) || (m_resinfo_table[resID].freq == 74176)) { |
| avpll_freq_index = 3; |
| } else if ((m_resinfo_table[resID].freq == 148500) || (m_resinfo_table[resID].freq == 148352)) { |
| if (resID == RES_1080I60 || resID == RES_1080I5994 || resID == RES_1080I50) |
| avpll_freq_index = 3; |
| else |
| avpll_freq_index = 5; |
| } else { |
| return (MV_THINVPP_EBADPARAM); |
| } |
| |
| if (bit_depth == OUTPUT_BIT_DEPTH_12BIT) { |
| deep_color_index = 2; |
| freq_factor = 15.0; |
| } else if (bit_depth == OUTPUT_BIT_DEPTH_10BIT) { |
| deep_color_index = 1; |
| freq_factor = 12.5; |
| } else if (bit_depth == OUTPUT_BIT_DEPTH_8BIT) { |
| deep_color_index = 0; |
| freq_factor = 10.0; |
| } else { |
| return (MV_THINVPP_EBADPARAM); |
| } |
| |
| ppm1k_en = NeedAVPLL_PPM1K(resID); |
| |
| diag_videoFreq_A(avpll_freq_index, deep_color_index, ppm1k_en, freq_factor, 7); |
| |
| delay_10ns(2000000); |
| |
| semaphore_pop(thinvpp_obj->pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr, 1); |
| semaphore_clr_full(thinvpp_obj->pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr); |
| do { |
| instat = semaphore_chk_full(thinvpp_obj->pSemHandle, -1); |
| } while (!(bTST(instat, avioDhubSemMap_vpp_vppCPCB0_intr))); |
| |
| THINVPP_BCMBUF_HardwareTrans_Direct(1, cmd_THINVPP_SetHdmiVideoFmt, sizeof(cmd_THINVPP_SetHdmiVideoFmt)); |
| |
| return (MV_THINVPP_OK); |
| } |
| |