blob: 0daa54aa6cf555b31699e6ffc098699d7263e296 [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.
********************************************************************************/
#include "fastlogo.h"
#include "galois_io.h"
#include "api_dhub.h"
#include "api_avio_dhub.h"
#include "Galois_memmap.h"
#include "gicDiag.h"
#include "pic.h"
#include "thinvpp.h"
#include "error_logo_data.h"
#include "normal_logo_data.h"
#include "avpll.h"
#ifndef bTST
#define bTST(x, b) (((x) >> (b)) & 1)
#endif
#ifndef BFM_HOST_Bus_Write32
#define BFM_HOST_Bus_Write32 GA_REG_WORD32_WRITE
#endif
volatile unsigned logo_isr_count;
#define printf(fmt...)
#ifndef EMMC_BOOT
extern void IRQ_Handler(void);
static void InstallHighHandler(unsigned int handlerAddr, unsigned int vector)
{
//load PC with content at current PC + 0x38,
//since current PC is vector+0x8, the handler should be at vector+0x40
BFM_HOST_Bus_Write32(vector, 0xE59FF038);
BFM_HOST_Bus_Write32(vector+0x40, handlerAddr);
}
static void EnableIRQ(void)
{
__asm__
__volatile__(
"MRS r0, CPSR" "\n\t"
"BIC r0, r0, #0x80" "\n\t"
"MSR CPSR, r0" "\n\t"
:
:
:"r0"
);
}
#endif
static void showlogo_init_irq(void)
{
unsigned cpu_id=0;
#ifdef EMMC_BOOT
//bootloader.c should have called do_emmcinit() to setup the irq
#else
//printf("%s, InstallHighHandler\n", __FUNCTION__) ;
InstallHighHandler((unsigned int)IRQ_Handler, MEMMAP_HIGH_EXCEPT_IRQ_REG);
//GIC distribution interface is only needed to be initialized once
//but the CPU interface needs to be initalized by both CPU cores
//CPU interface registers are banked (same address)
//So we will have both first and second CPU to call the same funtion
//printf("%s, initMPGIC\n", __FUNCTION__) ;
initMPGIC();
//printf("%s, EnableIRQ\n", __FUNCTION__) ;
EnableIRQ();
#endif
printf("[showlogo] Enable IRQ_dHubIntrAvio0(0x%x) for cpu %u\n", MP_BERLIN_INTR_ID(IRQ_dHubIntrAvio0), cpu_id);
diag_GICSetInt(cpu_id, MP_BERLIN_INTR_ID(IRQ_dHubIntrAvio0), INT_ENABLE);
}
static VBUF_INFO vbuf;
int showlogo_start(int error)
{
VPP_WIN_ATTR showlogo_attr;
VPP_WIN showlogo_win;
int yuv_logo_width, yuv_logo_height, yuv_logo_stride;
void *yuv_logo;
if (error) {
yuv_logo_width = error_yuv_logo_width;
yuv_logo_height = error_yuv_logo_height;
yuv_logo = error_yuv_logo;
} else {
yuv_logo_width = normal_yuv_logo_width;
yuv_logo_height = normal_yuv_logo_height;
yuv_logo = normal_yuv_logo;
}
yuv_logo_stride = yuv_logo_width * 2;
printf("[showlogo] start");
logo_isr_count = 0;
showlogo_init_irq();
vbuf.m_disp_offset = 0;
vbuf.m_active_left = (720 - yuv_logo_width)/2; // at center
vbuf.m_active_top = (480 - yuv_logo_height)/2; // at center
// adjust the following three fields to reflect the actual logo dimensions
vbuf.m_buf_stride = yuv_logo_stride;
vbuf.m_active_width = yuv_logo_width;
vbuf.m_active_height = yuv_logo_height;
vbuf.alpha = 255;
vbuf.bgcolor = 0x00800080; // black
vbuf.m_pbuf_start = (void *) yuv_logo;
printf("[showlogo] frame start at 0x%x\n", vbuf.m_pbuf_start) ;
MV_THINVPP_SetMainDisplayFrame(&vbuf);
showlogo_win.x = 0;
showlogo_win.y = 0;
showlogo_win.width = 720;
showlogo_win.height = 480;
showlogo_attr.bgcolor = vbuf.bgcolor;
showlogo_attr.alpha = vbuf.alpha;
MV_THINVPP_OpenDispWindow(PLANE_MAIN, &showlogo_win, &showlogo_attr);
return 0;
}
int showlogo_stop()
{
printf("[showlogo] isr_count=%u\n", logo_isr_count) ;
MV_THINVPP_CloseDispWindow();
MV_THINVPP_Stop();
MV_THINVPP_Destroy();
MV_THINVPP_Create(MEMMAP_VPP_REG_BASE, THINVPP_OPTION_DEFAULT);
MV_THINVPP_Reset();
MV_THINVPP_Config();
MV_THINVPP_SetCPCBOutputResolution(CPCB_1, RES_525P5994, OUTPUT_BIT_DEPTH_8BIT);
printf("[showlogo] stopped\n");
return 0;
}
void showlogo_isr(void)
{
int instat;
HDL_semaphore *pSemHandle;
++logo_isr_count;
/* VPP interrupt handling */
pSemHandle = dhub_semaphore(&VPP_dhubHandle.dhub);
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);
THINVPP_CPCB_ISR_service(thinvpp_obj, CPCB_1);
}
}
void fastlogo_init(void)
{
printf("[fastlogo] init.");
AVPLL_Enable();
DhubInitialization(0, VPP_DHUB_BASE, VPP_HBO_SRAM_BASE,
&VPP_dhubHandle, VPP_config, VPP_NUM_OF_CHANNELS);
DhubInitialization(0, AG_DHUB_BASE, AG_HBO_SRAM_BASE,
&AG_dhubHandle, AG_config, AG_NUM_OF_CHANNELS);
MV_THINVPP_Create(MEMMAP_VPP_REG_BASE, THINVPP_OPTION_SHOWLOGO);
MV_THINVPP_Reset();
MV_THINVPP_Config();
MV_THINVPP_SetCPCBOutputResolution(CPCB_1, RES_525P5994, OUTPUT_BIT_DEPTH_8BIT);
printf("[fastlogo] started.\n");
}