blob: 3a874a0824b89150a7411ae55839eaaf08dec378 [file] [log] [blame] [edit]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
/* System Headers */
#include <config.h>
#include <asm/arch/io.h>
#include <amlogic/cpu_id.h>
#include <asm/arch/cpu.h>
#include <asm/arch/timer.h>
#include <div64.h>
/* Local Headers */
#include <amlogic/media/vout/aml_vmode.h>
#ifdef CONFIG_AML_CANVAS
#include <amlogic/canvas.h>
#endif
#ifdef CONFIG_AML_VOUT
#include <amlogic/media/vout/aml_vout.h>
#endif
#include <amlogic/fb.h>
#include <video_fb.h>
#include <asm/arch/register.h>
/* Local Headers */
#include "osd_canvas.h"
#include "osd_log.h"
#include "osd_io.h"
#include "osd_hw.h"
#include "osd_hw_def.h"
#include "osd_fb.h"
#include "vpp.h"
#include <amlogic/media/dv/dolby_vision.h>
static bool vsync_hit;
static bool osd_vf_need_update;
unsigned int osd_log_level;
static unsigned int logo_loaded = 0;
#ifdef CONFIG_AM_VIDEO
static struct vframe_s vf;
static struct vframe_provider_s osd_vf_prov;
static unsigned char osd_vf_prov_init;
#endif
static int g_vf_visual_width;
static int g_vf_width;
static int g_vf_height;
static int g_rotation_width;
static int g_rotation_height;
static int use_h_filter_mode = -1;
static int use_v_filter_mode = -1;
static unsigned int osd_h_filter_mode = 1;
static unsigned int osd_v_filter_mode = 1;
extern GraphicDevice fb_gdev;
static void independ_path_default_regs(void);
static void fix_vpu_clk2_default_regs(void);
static int pi_enable;
struct fb_layout_s fb_layout[OSD_MAX];
#ifdef AML_C3_DISPLAY
#define VOUT_OSD1_UNSUPPORT VOUT_OSD1_TCOLOR_AG0
static void osd_setting_vout_blend(void);
struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
{
VOUT_OSD1_CTRL_STAT,
VOUT_OSD1_CTRL_STAT2,
VOUT_OSD1_COLOR_ADDR,
VOUT_OSD1_COLOR,
VOUT_OSD1_TCOLOR_AG0,
VOUT_OSD1_TCOLOR_AG1,
VOUT_OSD1_TCOLOR_AG2,
VOUT_OSD1_TCOLOR_AG3,
VOUT_OSD1_BLK0_CFG_W0,
VOUT_OSD1_BLK0_CFG_W1,
VOUT_OSD1_BLK0_CFG_W2,
VOUT_OSD1_BLK0_CFG_W3,
VOUT_OSD1_BLK0_CFG_W4,
VOUT_OSD1_BLK1_CFG_W4,
VOUT_OSD1_BLK2_CFG_W4,
VOUT_OSD1_FIFO_CTRL_STAT,
VOUT_OSD1_SCALE_COEF_IDX,
VOUT_OSD1_SCALE_COEF,
VOUT_OSD1_VSC_PHASE_STEP,
VOUT_OSD1_VSC_INI_PHASE,
VOUT_OSD1_VSC_CTRL0,
VOUT_OSD1_HSC_PHASE_STEP,
VOUT_OSD1_HSC_INI_PHASE,
VOUT_OSD1_HSC_CTRL0,
VOUT_OSD1_SC_DUMMY_DATA,
VOUT_OSD1_SC_CTRL0,
VOUT_OSD1_SCI_WH_M1,
VOUT_OSD1_SCO_H_START_END,
VOUT_OSD1_SCO_V_START_END,
VOUT_OSD1_UNSUPPORT,
VOUT_OSD1_UNSUPPORT,
},
};
#endif
#ifdef AML_OSD_HIGH_VERSION
#define VIU2_OSD1_UNSUPPORT VIU_OSD2_TCOLOR_AG3
#ifdef reg_define
struct hw_encp_reg_s hw_vout_reg = {
ENCP_VIDEO_MODE,
ENCP_INFO_READ,
ENCP_VIDEO_VAVON_BLINE,
ENCL_INFO_READ,
ENCL_VIDEO_VAVON_BLINE,
ENCI_INFO_READ,
ENCI_VFIFO2VD_LINE_TOP_START,
ENCT_INFO_READ,
ENCT_VIDEO_VAVON_BLINE,
};
#endif
#if defined(AML_S5_DISPLAY)
struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
{
VIU_OSD1_CTRL_STAT,
VIU_OSD1_CTRL_STAT2,
VIU_OSD1_COLOR_ADDR,
VIU_OSD1_COLOR,
VIU_OSD1_TCOLOR_AG0,
VIU_OSD1_TCOLOR_AG1,
VIU_OSD1_TCOLOR_AG2,
VIU_OSD1_TCOLOR_AG3,
VIU_OSD1_BLK0_CFG_W0,
VIU_OSD1_BLK0_CFG_W1,
VIU_OSD1_BLK0_CFG_W2,
VIU_OSD1_BLK0_CFG_W3,
VIU_OSD1_BLK0_CFG_W4,
VIU_OSD1_BLK1_CFG_W4,
VIU_OSD1_BLK2_CFG_W4,
VIU_OSD1_FIFO_CTRL_STAT,
OSD1_PROC_SCALE_COEF_IDX,
OSD1_PROC_SCALE_COEF,
OSD1_PROC_VSC_PHASE_STEP,
OSD1_PROC_VSC_INI_PHASE,
OSD1_PROC_VSC_CTRL0,
OSD1_PROC_HSC_PHASE_STEP,
OSD1_PROC_HSC_INI_PHASE,
OSD1_PROC_HSC_CTRL0,
OSD1_PROC_SC_DUMMY_DATA,
OSD1_PROC_SC_CTRL0,
OSD1_PROC_SCI_WH_M1,
OSD1_PROC_SCO_H_START_END,
OSD1_PROC_SCO_V_START_END,
OSD1_PROC_IN_SIZE,
OSD1_PROC_OUT_SIZE,
},
{
VIU_OSD2_CTRL_STAT,
VIU_OSD2_CTRL_STAT2,
VIU_OSD2_COLOR_ADDR,
VIU_OSD2_COLOR,
VIU_OSD2_TCOLOR_AG0,
VIU_OSD2_TCOLOR_AG1,
VIU_OSD2_TCOLOR_AG2,
VIU_OSD2_TCOLOR_AG3,
VIU_OSD2_BLK0_CFG_W0,
VIU_OSD2_BLK0_CFG_W1,
VIU_OSD2_BLK0_CFG_W2,
VIU_OSD2_BLK0_CFG_W3,
VIU_OSD2_BLK0_CFG_W4,
VIU_OSD2_BLK1_CFG_W4,
VIU_OSD2_BLK2_CFG_W4,
VIU_OSD2_FIFO_CTRL_STAT,
OSD2_PROC_SCALE_COEF_IDX,
OSD2_PROC_SCALE_COEF,
OSD2_PROC_VSC_PHASE_STEP,
OSD2_PROC_VSC_INI_PHASE,
OSD2_PROC_VSC_CTRL0,
OSD2_PROC_HSC_PHASE_STEP,
OSD2_PROC_HSC_INI_PHASE,
OSD2_PROC_HSC_CTRL0,
OSD2_PROC_SC_DUMMY_DATA,
OSD2_PROC_SC_CTRL0,
OSD2_PROC_SCI_WH_M1,
OSD2_PROC_SCO_H_START_END,
OSD2_PROC_SCO_V_START_END,
OSD2_PROC_IN_SIZE,
OSD2_PROC_OUT_SIZE,
},
{
VIU_OSD3_CTRL_STAT,
VIU_OSD3_CTRL_STAT2,
VIU_OSD3_COLOR_ADDR,
VIU_OSD3_COLOR,
VIU_OSD3_TCOLOR_AG0,
VIU_OSD3_TCOLOR_AG1,
VIU_OSD3_TCOLOR_AG2,
VIU_OSD3_TCOLOR_AG3,
VIU_OSD3_BLK0_CFG_W0,
VIU_OSD3_BLK0_CFG_W1,
VIU_OSD3_BLK0_CFG_W2,
VIU_OSD3_BLK0_CFG_W3,
VIU_OSD3_BLK0_CFG_W4,
VIU_OSD3_BLK1_CFG_W4,
VIU_OSD3_BLK2_CFG_W4,
VIU_OSD3_FIFO_CTRL_STAT,
OSD3_PROC_SCALE_COEF_IDX,
OSD3_PROC_SCALE_COEF,
OSD3_PROC_VSC_PHASE_STEP,
OSD3_PROC_VSC_INI_PHASE,
OSD3_PROC_VSC_CTRL0,
OSD3_PROC_HSC_PHASE_STEP,
OSD3_PROC_HSC_INI_PHASE,
OSD3_PROC_HSC_CTRL0,
OSD3_PROC_SC_DUMMY_DATA,
OSD3_PROC_SC_CTRL0,
OSD3_PROC_SCI_WH_M1,
OSD3_PROC_SCO_H_START_END,
OSD3_PROC_SCO_V_START_END,
OSD3_PROC_IN_SIZE,
OSD3_PROC_OUT_SIZE,
},
};
#elif defined(AML_T7_DISPLAY)
struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
{
VIU_OSD1_CTRL_STAT,
VIU_OSD1_CTRL_STAT2,
VIU_OSD1_COLOR_ADDR,
VIU_OSD1_COLOR,
VIU_OSD1_TCOLOR_AG0,
VIU_OSD1_TCOLOR_AG1,
VIU_OSD1_TCOLOR_AG2,
VIU_OSD1_TCOLOR_AG3,
VIU_OSD1_BLK0_CFG_W0,
VIU_OSD1_BLK0_CFG_W1,
VIU_OSD1_BLK0_CFG_W2,
VIU_OSD1_BLK0_CFG_W3,
VIU_OSD1_BLK0_CFG_W4,
VIU_OSD1_BLK1_CFG_W4,
VIU_OSD1_BLK2_CFG_W4,
VIU_OSD1_FIFO_CTRL_STAT,
VPP_OSD_SCALE_COEF_IDX,
VPP_OSD_SCALE_COEF,
VPP_OSD_VSC_PHASE_STEP,
VPP_OSD_VSC_INI_PHASE,
VPP_OSD_VSC_CTRL0,
VPP_OSD_HSC_PHASE_STEP,
VPP_OSD_HSC_INI_PHASE,
VPP_OSD_HSC_CTRL0,
VPP_OSD_SC_DUMMY_DATA,
VPP_OSD_SC_CTRL0,
VPP_OSD_SCI_WH_M1,
VPP_OSD_SCO_H_START_END,
VPP_OSD_SCO_V_START_END,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
{
VIU_OSD2_CTRL_STAT,
VIU_OSD2_CTRL_STAT2,
VIU_OSD2_COLOR_ADDR,
VIU_OSD2_COLOR,
VIU_OSD2_TCOLOR_AG0,
VIU_OSD2_TCOLOR_AG1,
VIU_OSD2_TCOLOR_AG2,
VIU_OSD2_TCOLOR_AG3,
VIU_OSD2_BLK0_CFG_W0,
VIU_OSD2_BLK0_CFG_W1,
VIU_OSD2_BLK0_CFG_W2,
VIU_OSD2_BLK0_CFG_W3,
VIU_OSD2_BLK0_CFG_W4,
VIU_OSD2_BLK1_CFG_W4,
VIU_OSD2_BLK2_CFG_W4,
VIU_OSD2_FIFO_CTRL_STAT,
OSD2_SCALE_COEF_IDX,
OSD2_SCALE_COEF,
OSD2_VSC_PHASE_STEP,
OSD2_VSC_INI_PHASE,
OSD2_VSC_CTRL0,
OSD2_HSC_PHASE_STEP,
OSD2_HSC_INI_PHASE,
OSD2_HSC_CTRL0,
OSD2_SC_DUMMY_DATA,
OSD2_SC_CTRL0,
OSD2_SCI_WH_M1,
OSD2_SCO_H_START_END,
OSD2_SCO_V_START_END,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
{
VIU_OSD3_CTRL_STAT,
VIU_OSD3_CTRL_STAT2,
VIU_OSD3_COLOR_ADDR,
VIU_OSD3_COLOR,
VIU_OSD3_TCOLOR_AG0,
VIU_OSD3_TCOLOR_AG1,
VIU_OSD3_TCOLOR_AG2,
VIU_OSD3_TCOLOR_AG3,
VIU_OSD3_BLK0_CFG_W0,
VIU_OSD3_BLK0_CFG_W1,
VIU_OSD3_BLK0_CFG_W2,
VIU_OSD3_BLK0_CFG_W3,
VIU_OSD3_BLK0_CFG_W4,
VIU_OSD3_BLK1_CFG_W4,
VIU_OSD3_BLK2_CFG_W4,
VIU_OSD3_FIFO_CTRL_STAT,
OSD34_SCALE_COEF_IDX,
OSD34_SCALE_COEF,
OSD34_VSC_PHASE_STEP,
OSD34_VSC_INI_PHASE,
OSD34_VSC_CTRL0,
OSD34_HSC_PHASE_STEP,
OSD34_HSC_INI_PHASE,
OSD34_HSC_CTRL0,
OSD34_SC_DUMMY_DATA,
OSD34_SC_CTRL0,
OSD34_SCI_WH_M1,
OSD34_SCO_H_START_END,
OSD34_SCO_V_START_END,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
{
VIU_OSD4_CTRL_STAT,
VIU_OSD4_CTRL_STAT2,
VIU_OSD4_COLOR_ADDR,
VIU_OSD4_COLOR,
VIU_OSD4_TCOLOR_AG0,
VIU_OSD4_TCOLOR_AG1,
VIU_OSD4_TCOLOR_AG2,
VIU_OSD4_TCOLOR_AG3,
VIU_OSD4_BLK0_CFG_W0,
VIU_OSD4_BLK0_CFG_W1,
VIU_OSD4_BLK0_CFG_W2,
VIU_OSD4_BLK0_CFG_W3,
VIU_OSD4_BLK0_CFG_W4,
VIU_OSD4_BLK1_CFG_W4,
VIU_OSD4_BLK2_CFG_W4,
VIU_OSD4_FIFO_CTRL_STAT,
OSD4_SCALE_COEF_IDX,
OSD4_SCALE_COEF,
OSD4_VSC_PHASE_STEP,
OSD4_VSC_INI_PHASE,
OSD4_VSC_CTRL0,
OSD4_HSC_PHASE_STEP,
OSD4_HSC_INI_PHASE,
OSD4_HSC_CTRL0,
OSD4_SC_DUMMY_DATA,
OSD4_SC_CTRL0,
OSD4_SCI_WH_M1,
OSD4_SCO_H_START_END,
OSD4_SCO_V_START_END,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
};
#else
struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
{
VIU_OSD1_CTRL_STAT,
VIU_OSD1_CTRL_STAT2,
VIU_OSD1_COLOR_ADDR,
VIU_OSD1_COLOR,
VIU_OSD1_TCOLOR_AG0,
VIU_OSD1_TCOLOR_AG1,
VIU_OSD1_TCOLOR_AG2,
VIU_OSD1_TCOLOR_AG3,
VIU_OSD1_BLK0_CFG_W0,
VIU_OSD1_BLK0_CFG_W1,
VIU_OSD1_BLK0_CFG_W2,
VIU_OSD1_BLK0_CFG_W3,
VIU_OSD1_BLK0_CFG_W4,
VIU_OSD1_BLK1_CFG_W4,
VIU_OSD1_BLK2_CFG_W4,
VIU_OSD1_FIFO_CTRL_STAT,
VPP_OSD_SCALE_COEF_IDX,
VPP_OSD_SCALE_COEF,
VPP_OSD_VSC_PHASE_STEP,
VPP_OSD_VSC_INI_PHASE,
VPP_OSD_VSC_CTRL0,
VPP_OSD_HSC_PHASE_STEP,
VPP_OSD_HSC_INI_PHASE,
VPP_OSD_HSC_CTRL0,
VPP_OSD_SC_DUMMY_DATA,
VPP_OSD_SC_CTRL0,
VPP_OSD_SCI_WH_M1,
VPP_OSD_SCO_H_START_END,
VPP_OSD_SCO_V_START_END,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
{
VIU_OSD2_CTRL_STAT,
VIU_OSD2_CTRL_STAT2,
VIU_OSD2_COLOR_ADDR,
VIU_OSD2_COLOR,
VIU_OSD2_TCOLOR_AG0,
VIU_OSD2_TCOLOR_AG1,
VIU_OSD2_TCOLOR_AG2,
VIU_OSD2_TCOLOR_AG3,
VIU_OSD2_BLK0_CFG_W0,
VIU_OSD2_BLK0_CFG_W1,
VIU_OSD2_BLK0_CFG_W2,
VIU_OSD2_BLK0_CFG_W3,
VIU_OSD2_BLK0_CFG_W4,
VIU_OSD2_BLK1_CFG_W4,
VIU_OSD2_BLK2_CFG_W4,
VIU_OSD2_FIFO_CTRL_STAT,
VPP_OSD_SCALE_COEF_IDX,
VPP_OSD_SCALE_COEF,
VPP_OSD_VSC_PHASE_STEP,
VPP_OSD_VSC_INI_PHASE,
VPP_OSD_VSC_CTRL0,
VPP_OSD_HSC_PHASE_STEP,
VPP_OSD_HSC_INI_PHASE,
VPP_OSD_HSC_CTRL0,
VPP_OSD_SC_DUMMY_DATA,
VPP_OSD_SC_CTRL0,
VPP_OSD_SCI_WH_M1,
VPP_OSD_SCO_H_START_END,
VPP_OSD_SCO_V_START_END,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
{
VIU2_OSD1_CTRL_STAT,
VIU2_OSD1_CTRL_STAT2,
VIU2_OSD1_COLOR_ADDR,
VIU2_OSD1_COLOR,
VIU2_OSD1_TCOLOR_AG0,
VIU2_OSD1_TCOLOR_AG1,
VIU2_OSD1_TCOLOR_AG2,
VIU2_OSD1_TCOLOR_AG3,
VIU2_OSD1_BLK0_CFG_W0,
VIU2_OSD1_BLK0_CFG_W1,
VIU2_OSD1_BLK0_CFG_W2,
VIU2_OSD1_BLK0_CFG_W3,
VIU2_OSD1_BLK0_CFG_W4,
VIU2_OSD1_BLK1_CFG_W4,
VIU2_OSD1_BLK2_CFG_W4,
VIU2_OSD1_FIFO_CTRL_STAT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
{
VIU2_OSD1_CTRL_STAT,
VIU2_OSD1_CTRL_STAT2,
VIU2_OSD1_COLOR_ADDR,
VIU2_OSD1_COLOR,
VIU2_OSD1_TCOLOR_AG0,
VIU2_OSD1_TCOLOR_AG1,
VIU2_OSD1_TCOLOR_AG2,
VIU2_OSD1_TCOLOR_AG3,
VIU2_OSD1_BLK0_CFG_W0,
VIU2_OSD1_BLK0_CFG_W1,
VIU2_OSD1_BLK0_CFG_W2,
VIU2_OSD1_BLK0_CFG_W3,
VIU2_OSD1_BLK0_CFG_W4,
VIU2_OSD1_BLK1_CFG_W4,
VIU2_OSD1_BLK2_CFG_W4,
VIU2_OSD1_FIFO_CTRL_STAT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
VIU2_OSD1_UNSUPPORT,
},
};
#endif
#endif
#ifdef AML_C3_DISPLAY
struct hw_osd_vout_blend_reg_s hw_osd_vout_blend_reg = {
VPU_VOUT_IRQ_CTRL,
VPU_VOUT_BLEND_CTRL,
VPU_VOUT_BLEND_DUMDATA,
VPU_VOUT_BLEND_SIZE,
VPU_VOUT_BLD_SRC0_HPOS,
VPU_VOUT_BLD_SRC0_VPOS,
VPU_VOUT_BLD_SRC1_HPOS,
VPU_VOUT_BLD_SRC1_VPOS
};
struct hw_osd_vout_csc_reg_s hw_osd_vout_csc_reg = {
VOUT_OSD1_CSC_COEF00_01,
VOUT_OSD1_CSC_COEF02_10,
VOUT_OSD1_CSC_COEF11_12,
VOUT_OSD1_CSC_COEF20_21,
VOUT_OSD1_CSC_COEF22,
VOUT_OSD1_CSC_COEF30_31,
VOUT_OSD1_CSC_COEF32_40,
VOUT_OSD1_CSC_COEF41_42,
VOUT_OSD1_CSC_CLIP,
VOUT_OSD1_CSC_OFFSET0_1,
VOUT_OSD1_CSC_OFFSET2,
VOUT_OSD1_CSC_PRE_OFFSET0_1,
VOUT_OSD1_CSC_PRE_OFFSET2,
VOUT_OSD1_CSC_EN_CTRL
};
#endif
static unsigned int osd_filter_coefs_bicubic_sharp[] = {
0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300,
0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
0xf84848f8
};
static unsigned int osd_filter_coefs_bicubic[] = { /* bicubic coef0 */
0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, 0xfd7e0500, 0xfc7e0600,
0xfb7d0800, 0xfb7c0900, 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, 0xf76f1dfd, 0xf76d1ffd,
0xf76b21fd, 0xf76824fd, 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, 0xf8523cfa, 0xf8503ff9,
0xf84d42f9, 0xf84a45f9, 0xf84848f8
};
static unsigned int osd_filter_coefs_bilinear[] = { /* 2 point bilinear coef1 */
0x00800000, 0x007e0200, 0x007c0400, 0x007a0600, 0x00780800, 0x00760a00,
0x00740c00, 0x00720e00, 0x00701000, 0x006e1200, 0x006c1400, 0x006a1600,
0x00681800, 0x00661a00, 0x00641c00, 0x00621e00, 0x00602000, 0x005e2200,
0x005c2400, 0x005a2600, 0x00582800, 0x00562a00, 0x00542c00, 0x00522e00,
0x00503000, 0x004e3200, 0x004c3400, 0x004a3600, 0x00483800, 0x00463a00,
0x00443c00, 0x00423e00, 0x00404000
};
static unsigned int osd_filter_coefs_2point_bilinear[] = {
/* 2 point bilinear, bank_length == 2 coef2 */
0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, 0x78080000, 0x760a0000,
0x740c0000, 0x720e0000, 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, 0x60200000, 0x5e220000,
0x5c240000, 0x5a260000, 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, 0x48380000, 0x463a0000,
0x443c0000, 0x423e0000, 0x40400000
};
/* filt_triangle, point_num =3, filt_len =2.6, group_num = 64 */
static unsigned int osd_filter_coefs_3point_triangle_sharp[] = {
0x40400000, 0x3e420000, 0x3d430000, 0x3b450000,
0x3a460000, 0x38480000, 0x37490000, 0x354b0000,
0x344c0000, 0x324e0000, 0x314f0000, 0x2f510000,
0x2e520000, 0x2c540000, 0x2b550000, 0x29570000,
0x28580000, 0x265a0000, 0x245c0000, 0x235d0000,
0x215f0000, 0x20600000, 0x1e620000, 0x1d620100,
0x1b620300, 0x19630400, 0x17630600, 0x15640700,
0x14640800, 0x12640a00, 0x11640b00, 0x0f650c00,
0x0d660d00
};
static unsigned int osd_filter_coefs_3point_triangle[] = {
0x40400000, 0x3f400100, 0x3d410200, 0x3c410300,
0x3a420400, 0x39420500, 0x37430600, 0x36430700,
0x35430800, 0x33450800, 0x32450900, 0x31450a00,
0x30450b00, 0x2e460c00, 0x2d460d00, 0x2c470d00,
0x2b470e00, 0x29480f00, 0x28481000, 0x27481100,
0x26491100, 0x25491200, 0x24491300, 0x234a1300,
0x224a1400, 0x214a1500, 0x204a1600, 0x1f4b1600,
0x1e4b1700, 0x1d4b1800, 0x1c4c1800, 0x1b4c1900,
0x1a4c1a00
};
static unsigned int osd_filter_coefs_4point_triangle[] = {
0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101,
0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303,
0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505,
0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707,
0x18382808, 0x18382808, 0x17372909, 0x17372909,
0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b,
0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d,
0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f,
0x10303010
};
/* 4th order (cubic) b-spline */
/* filt_cubic point_num =4, filt_len =4, group_num = 64 */
static unsigned int vpp_filter_coefs_4point_bspline[] = {
0x15561500, 0x14561600, 0x13561700, 0x12561800,
0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
0x05473301, 0x05463401, 0x04453601, 0x04433702,
0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
0x033d3d03
};
/* filt_quadratic, point_num =3, filt_len =3, group_num = 64 */
static unsigned int osd_filter_coefs_3point_bspline[] = {
0x40400000, 0x3e420000, 0x3c440000, 0x3a460000,
0x38480000, 0x364a0000, 0x344b0100, 0x334c0100,
0x314e0100, 0x304f0100, 0x2e500200, 0x2c520200,
0x2a540200, 0x29540300, 0x27560300, 0x26570300,
0x24580400, 0x23590400, 0x215a0500, 0x205b0500,
0x1e5c0600, 0x1d5c0700, 0x1c5d0700, 0x1a5e0800,
0x195e0900, 0x185e0a00, 0x175f0a00, 0x15600b00,
0x14600c00, 0x13600d00, 0x12600e00, 0x11600f00,
0x10601000
};
static unsigned int *filter_table[] = {
osd_filter_coefs_bicubic_sharp,
osd_filter_coefs_bicubic,
osd_filter_coefs_bilinear,
osd_filter_coefs_2point_bilinear,
osd_filter_coefs_3point_triangle_sharp,
osd_filter_coefs_3point_triangle,
osd_filter_coefs_4point_triangle,
vpp_filter_coefs_4point_bspline,
osd_filter_coefs_3point_bspline
};
#define OSD_TYPE_TOP_FIELD 0
#define OSD_TYPE_BOT_FIELD 1
int osd_get_chip_type(void)
{
unsigned int cpu_type;
cpu_type = get_cpu_id().family_id;
return cpu_type;
}
static void osd_vpu_power_on(void)
{
}
#ifndef AML_T7_DISPLAY
#ifdef AML_OSD_HIGH_VERSION
static void osd_vpu_power_on_viu2(void)
{
}
#endif
#endif
void osd_set_log_level(int level)
{
osd_log_level = level;
}
void osd_get_hw_para(struct hw_para_s **para)
{
*para = &osd_hw;
return;
}
#ifdef CONFIG_AM_VIDEO
static struct vframe_s *osd_vf_peek(void *arg)
{
if (osd_vf_need_update && (vf.width > 0) && (vf.height > 0))
return &vf;
else
return NULL;
}
static struct vframe_s *osd_vf_get(void *arg)
{
if (osd_vf_need_update) {
vf_ext_light_unreg_provider(&osd_vf_prov);
osd_vf_need_update = false;
return &vf;
}
return NULL;
}
#define PROVIDER_NAME "osd"
static const struct vframe_operations_s osd_vf_provider = {
.peek = osd_vf_peek,
.get = osd_vf_get,
.put = NULL,
};
#endif
static inline void osd_update_3d_mode(int enable_osd1, int enable_osd2,
int enable_osd3, int enable_viu2_osd1)
{
if (enable_osd1)
osd1_update_disp_3d_mode();
if (enable_osd2)
osd2_update_disp_3d_mode();
if (enable_osd3)
osd3_update_disp_3d_mode();
if (enable_viu2_osd1)
viu2_osd1_update_disp_3d_mode();
}
#if 1
static void get_encp_line(int *enc_line, int *active_line_begin)
{
#ifndef AML_C3_DISPLAY
unsigned int reg = 0;
unsigned int viu_sel;
int osd_index;
osd_index = get_osd_layer();
if (osd_index < VIU2_OSD1)
viu_sel = osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3;
else
viu_sel = (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) >> 2) & 0x3;
switch (viu_sel) {
case 0:
reg = osd_reg_read(ENCL_INFO_READ);
*active_line_begin =
osd_reg_read(ENCL_VIDEO_VAVON_BLINE);
break;
case 1:
reg = osd_reg_read(ENCI_INFO_READ);
*active_line_begin =
osd_reg_read(ENCI_VFIFO2VD_LINE_TOP_START);
break;
case 2:
reg = osd_reg_read(ENCP_INFO_READ);
*active_line_begin =
osd_reg_read(ENCP_VIDEO_VAVON_BLINE);
break;
case 3:
reg = osd_reg_read(ENCT_INFO_READ);
*active_line_begin =
osd_reg_read(ENCT_VIDEO_VAVON_BLINE);
break;
}
*enc_line = (reg >> 16) & 0x1fff;
*enc_line -= (*active_line_begin);
#endif
}
static inline void wait_vsync_wakeup(void)
{
#ifndef AML_C3_DISPLAY
int i = 0;
int enc_line = 0;
int active_line_begin;
int vsync_line = 0;
int line_after = 0;
#ifdef CONFIG_AML_VOUT
struct vinfo_s *info = NULL;
info = vout_get_current_vinfo();
vsync_line = info->field_height;
#endif
get_encp_line(&enc_line, &active_line_begin);
/* if current line is always zero */
if (enc_line == (0 - active_line_begin)) {
_udelay(50);
get_encp_line(&line_after, &active_line_begin);
if (enc_line == (0 - active_line_begin))
goto vsync_hit_flag;
}
while (enc_line < vsync_line) {
if (i > 100000) {
osd_logi("wait_vsync_wakeup exit\n");
break;
}
i++;
get_encp_line(&enc_line, &active_line_begin);
}
vsync_hit_flag:
vsync_hit = true;
#else
int enc_line = 0;
int active_line_begin;
get_encp_line(&enc_line, &active_line_begin);
#endif
}
#else
static int get_encp_line(int *enc_line)
{
int vsync_get = 0;
unsigned int reg = 0;
int field_status = 0;
static int pre_field_status = 0;
switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
case 0:
reg = osd_reg_read(ENCL_INFO_READ);
break;
case 1:
reg = osd_reg_read(ENCI_INFO_READ);
break;
case 2:
reg = osd_reg_read(ENCP_INFO_READ);
break;
case 3:
reg = osd_reg_read(ENCT_INFO_READ);
break;
}
*enc_line = (reg >> 16) & 0x1fff;
field_status = (reg >> 29) & 0x7;
if (field_status != pre_field_status)
vsync_get = 1;
pre_field_status = field_status;
return vsync_get;
}
static inline void wait_vsync_wakeup(void)
{
int i = 0;
int line = 0;
int vsync_get = 0;
vsync_get = get_encp_line(&line);
if ((line > 0) || vsync_get) {
while (!vsync_get) {
if (i>100000) {
osd_logi("wait_vsync_wakeup exit, i=%d\n", i);
break;
}
i++;
vsync_get = get_encp_line(&line);
}
}
vsync_hit = true;
}
#endif
static inline void walk_through_update_list(void)
{
u32 i, j;
for (i = 0; i < HW_OSD_COUNT; i++) {
j = 0;
while (osd_hw.updated[i] && j < HW_REG_INDEX_MAX) {
if (osd_hw.updated[i] & (1 << j)) {
osd_hw.reg[i][j].update_func();
remove_from_update_list(i, j);
}
j++;
}
}
}
static void osd_check_scan_mode(void)
{
#define VOUT_ENCI 1
#define VOUT_ENCP 2
#define VOUT_ENCT 3
int vmode = -1;
osd_hw.scan_mode = SCAN_MODE_PROGRESSIVE;
#ifdef CONFIG_AML_VOUT
vmode = vout_get_current_vmode();
#endif
switch (vmode) {
/* case VMODE_LCD:*/
case VMODE_480I:
case VMODE_480CVBS:
case VMODE_576I:
case VMODE_576CVBS:
case VMODE_1080I:
case VMODE_1080I_50HZ:
osd_hw.scan_mode = SCAN_MODE_INTERLACE;
break;
default:
break;
}
}
#ifdef AML_C3_DISPLAY
static void irq_clr_c3(void)
{
u32 data32, irq_src;
data32 = osd_reg_read(hw_osd_vout_blend_reg.vpu_vout_irq_ctrl);
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_A4) {
irq_src = data32 >> 16;
data32 |= irq_src;
} else {
data32 |= 0x01;
}
osd_reg_write(hw_osd_vout_blend_reg.vpu_vout_irq_ctrl, data32);
}
#endif
static void vsync_isr(void)
{
#ifndef AML_C3_DISPLAY
unsigned int odd_even;
unsigned int scan_line_number = 0;
#endif
unsigned int fb0_cfg_w0, fb1_cfg_w0;
#ifdef AML_C3_DISPLAY
irq_clr_c3();
#endif
osd_check_scan_mode();
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE) {
fb0_cfg_w0 = osd_reg_read(hw_osd_reg_array[0].osd_blk0_cfg_w0);
fb1_cfg_w0 = osd_reg_read(hw_osd_reg_array[1].osd_blk0_cfg_w0);
#ifndef AML_C3_DISPLAY
if (osd_reg_read(ENCP_VIDEO_MODE) & (1 << 12)) {
/* 1080I */
scan_line_number = ((osd_reg_read(ENCP_INFO_READ))
& 0x1fff0000) >> 16;
if ((osd_hw.pandata[OSD1].y_start % 2) == 0) {
if (scan_line_number >= 562) {
/* bottom field, odd lines*/
odd_even = 1;
} else {
/* top field, even lines*/
odd_even = 0;
}
} else {
if (scan_line_number >= 562) {
/* top field, even lines*/
odd_even = 0;
} else {
/* bottom field, odd lines*/
odd_even = 1;
}
}
} else {
if ((osd_hw.pandata[OSD1].y_start % 2) == 0)
odd_even = osd_reg_read(ENCI_INFO_READ) & 1;
else
odd_even = !(osd_reg_read(ENCI_INFO_READ) & 1);
}
#endif
fb0_cfg_w0 &= ~1;
fb1_cfg_w0 &= ~1;
#ifndef AML_C3_DISPLAY
fb0_cfg_w0 |= odd_even;
fb1_cfg_w0 |= odd_even;
#endif
osd_reg_write(hw_osd_reg_array[0].osd_blk0_cfg_w0, fb0_cfg_w0);
osd_reg_write(hw_osd_reg_array[1].osd_blk0_cfg_w0, fb1_cfg_w0);
}
/* go through update list */
if (!vsync_hit)
wait_vsync_wakeup();
walk_through_update_list();
osd_update_3d_mode(osd_hw.mode_3d[OSD1].enable,
osd_hw.mode_3d[OSD2].enable,
osd_hw.mode_3d[OSD3].enable,
osd_hw.mode_3d[VIU2_OSD1].enable);
}
void osd_wait_vsync_hw(void)
{
//mdelay(16);
vsync_isr();
vsync_hit = false;
}
int osd_set_scan_mode(u32 index)
{
u32 data32 = 0x0;
int vmode = -1;
int real_scan_mode = SCAN_MODE_INTERLACE;
#ifdef CONFIG_AML_VOUT
vmode = vout_get_current_vmode();
#endif
osd_hw.scan_mode = SCAN_MODE_PROGRESSIVE;
if (osd_hw.fb_for_4k2k) {
if (osd_hw.free_scale_enable[index])
osd_hw.scale_workaround = 1;
}
switch (vmode) {
/* case VMODE_LCD: */
case VMODE_480I:
case VMODE_480CVBS:
case VMODE_576I:
case VMODE_576CVBS:
if (osd_hw.free_scale_mode[index]) {
osd_hw.field_out_en = 1;
switch (osd_hw.free_scale_data[index].y_end) {
case 719:
osd_hw.bot_type = 2;
break;
case 1079:
osd_hw.bot_type = 3;
break;
default:
osd_hw.bot_type = 2;
break;
}
}
osd_hw.scan_mode = real_scan_mode = SCAN_MODE_INTERLACE;
break;
case VMODE_1080I:
case VMODE_1080I_50HZ:
#ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION
case VMODE_1080I_59HZ:
#endif
if (osd_hw.free_scale_mode[index]) {
osd_hw.field_out_en = 1;
switch (osd_hw.free_scale_data[index].y_end) {
case 719:
osd_hw.bot_type = 1;
break;
case 1079:
osd_hw.bot_type = 2;
break;
default:
osd_hw.bot_type = 1;
break;
}
}
osd_hw.scan_mode = real_scan_mode = SCAN_MODE_INTERLACE;
break;
case VMODE_4K2K_24HZ:
case VMODE_4K2K_25HZ:
case VMODE_4K2K_30HZ:
case VMODE_4K2K_SMPTE:
case VMODE_4K2K_SMPTE_25HZ:
case VMODE_4K2K_SMPTE_30HZ:
case VMODE_4K2K_SMPTE_50HZ:
case VMODE_4K2K_SMPTE_60HZ:
case VMODE_4K2K_SMPTE_50HZ_Y420:
case VMODE_4K2K_SMPTE_60HZ_Y420:
if (osd_hw.fb_for_4k2k) {
if (osd_hw.free_scale_enable[index])
osd_hw.scale_workaround = 1;
}
osd_hw.field_out_en = 0;
break;
default:
if (osd_hw.free_scale_mode[index])
osd_hw.field_out_en = 0;
break;
}
if (osd_hw.free_scale_enable[index])
osd_hw.scan_mode = SCAN_MODE_PROGRESSIVE;
if (index == OSD1) {
data32 = (osd_reg_read(hw_osd_reg_array[0].osd_blk0_cfg_w0) & 3) >> 1;
#ifndef AML_C3_DISPLAY
} else if (index == OSD2) {
if (real_scan_mode == SCAN_MODE_INTERLACE)
return 1;
/* data32 = (osd_reg_read(hw_osd_reg_array[1].osd_blk0_cfg_w0) & 3) >> 1; */
} else {
data32 = (osd_reg_read(VIU_OSD3_BLK0_CFG_W0) & 3) >> 1;
#endif
}
if (data32 == osd_hw.scan_mode)
return 1;
else
return 0;
}
void osd_set_gbl_alpha_hw(u32 index, u32 gbl_alpha)
{
if (osd_hw.gbl_alpha[index] != gbl_alpha) {
osd_hw.gbl_alpha[index] = gbl_alpha;
add_to_update_list(index, OSD_GBL_ALPHA);
osd_wait_vsync_hw();
}
}
u32 osd_get_gbl_alpha_hw(u32 index)
{
return osd_hw.gbl_alpha[index];
}
void osd_set_color_key_hw(u32 index, u32 color_index, u32 colorkey)
{
u8 r = 0, g = 0, b = 0, a = (colorkey & 0xff000000) >> 24;
u32 data32;
colorkey &= 0x00ffffff;
switch (color_index) {
case COLOR_INDEX_16_655:
r = (colorkey >> 10 & 0x3f) << 2;
g = (colorkey >> 5 & 0x1f) << 3;
b = (colorkey & 0x1f) << 3;
break;
case COLOR_INDEX_16_844:
r = colorkey >> 8 & 0xff;
g = (colorkey >> 4 & 0xf) << 4;
b = (colorkey & 0xf) << 4;
break;
case COLOR_INDEX_16_565:
r = (colorkey >> 11 & 0x1f) << 3;
g = (colorkey >> 5 & 0x3f) << 2;
b = (colorkey & 0x1f) << 3;
break;
case COLOR_INDEX_24_888_B:
b = colorkey >> 16 & 0xff;
g = colorkey >> 8 & 0xff;
r = colorkey & 0xff;
break;
case COLOR_INDEX_24_RGB:
case COLOR_INDEX_YUV_422:
r = colorkey >> 16 & 0xff;
g = colorkey >> 8 & 0xff;
b = colorkey & 0xff;
break;
}
data32 = r << 24 | g << 16 | b << 8 | a;
if (osd_hw.color_key[index] != data32) {
osd_hw.color_key[index] = data32;
osd_logd2("bpp:%d--r:0x%x g:0x%x b:0x%x ,a:0x%x\n",
color_index, r, g, b, a);
add_to_update_list(index, OSD_COLOR_KEY);
osd_wait_vsync_hw();
}
return;
}
void osd_srckey_enable_hw(u32 index, u8 enable)
{
if (enable != osd_hw.color_key_enable[index]) {
osd_hw.color_key_enable[index] = enable;
add_to_update_list(index, OSD_COLOR_KEY_ENABLE);
osd_wait_vsync_hw();
}
}
void osd_set_color_mode(u32 index, const struct color_bit_define_s *color)
{
if (color != osd_hw.color_info[index]) {
osd_hw.color_info[index] = color;
add_to_update_list(index, OSD_COLOR_MODE);
}
}
void osd_update_disp_axis_hw(
u32 index,
u32 display_h_start,
u32 display_h_end,
u32 display_v_start,
u32 display_v_end,
u32 xoffset,
u32 yoffset,
u32 mode_change)
{
struct pandata_s disp_data;
struct pandata_s pan_data;
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_M8) {
if (index == OSD2)
return;
}
if (NULL == osd_hw.color_info[index])
return;
disp_data.x_start = display_h_start;
disp_data.y_start = display_v_start;
disp_data.x_end = display_h_end;
disp_data.y_end = display_v_end;
pan_data.x_start = xoffset;
pan_data.x_end = xoffset + (display_h_end - display_h_start);
pan_data.y_start = yoffset;
pan_data.y_end = yoffset + (display_v_end - display_v_start);
/* if output mode change then reset pan ofFfset. */
memcpy(&osd_hw.pandata[index], &pan_data, sizeof(struct pandata_s));
memcpy(&osd_hw.dispdata[index], &disp_data, sizeof(struct pandata_s));
if (mode_change) /* modify pandata . */
add_to_update_list(index, OSD_COLOR_MODE);
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_wait_vsync_hw();
}
/* the return stride unit is 128bit(16bytes) */
static u32 line_stride_calc(u32 fmt_mode,
u32 hsize,
u32 stride_align_32bytes)
{
u32 line_stride = 0;
u32 line_stride_32bytes;
u32 line_stride_64bytes;
switch (fmt_mode) {
/* 2-bit LUT */
case COLOR_INDEX_02_PAL4:
line_stride = ((hsize << 1) + 127) >> 7;
break;
/* 4-bit LUT */
case COLOR_INDEX_04_PAL16:
line_stride = ((hsize << 2) + 127) >> 7;
break;
/* 8-bit LUT */
case COLOR_INDEX_08_PAL256:
line_stride = ((hsize << 3) + 127) >> 7;
break;
/* 4:2:2, 32-bit per 2 pixels */
case COLOR_INDEX_YUV_422:
line_stride = ((((hsize + 1) >> 1) << 5) + 127) >> 7;
break;
/* 16-bit LUT */
case COLOR_INDEX_16_655:
case COLOR_INDEX_16_844:
case COLOR_INDEX_16_6442:
case COLOR_INDEX_16_4444_R:
case COLOR_INDEX_16_4642_R:
case COLOR_INDEX_16_1555_A:
case COLOR_INDEX_16_4444_A:
case COLOR_INDEX_16_565:
line_stride = ((hsize << 4) + 127) >> 7;
break;
/* 32-bit LUT */
case COLOR_INDEX_32_BGRA:
case COLOR_INDEX_32_ABGR:
case COLOR_INDEX_32_RGBA:
case COLOR_INDEX_32_ARGB:
line_stride = ((hsize << 5) + 127) >> 7;
break;
/* 24-bit LUT */
case COLOR_INDEX_24_6666_A:
case COLOR_INDEX_24_6666_R:
case COLOR_INDEX_24_8565:
case COLOR_INDEX_24_5658:
case COLOR_INDEX_24_888_B:
case COLOR_INDEX_24_RGB:
line_stride = ((hsize << 4) + (hsize << 3) + 127) >> 7;
break;
}
line_stride_32bytes = ((line_stride + 1) >> 1) << 1;
line_stride_64bytes = ((line_stride + 3) >> 2) << 2;
/* need wr ddr is 32bytes aligned */
if (stride_align_32bytes)
line_stride = line_stride_32bytes;
else
line_stride = line_stride_64bytes;
return line_stride;
}
#ifdef AML_OSD_HIGH_VERSION
/* only one layer */
void osd_setting_default_hwc(u32 index, struct pandata_s *disp_data)
{
u32 width, height;
u32 blend2_premult_en = 3, din_premult_en = 0;
u32 blend_din_en = 0x5;
/* blend_din0 input to blend0 */
u32 din0_byp_blend = 0;
/* blend1_dout to blend2 */
u32 din2_osd_sel = 0;
/* blend1_din3 input to blend1 */
u32 din3_osd_sel = 0;
u32 din_reoder_sel = 0x1;
u32 postbld_src3_sel = 3, postbld_src4_sel = 0;
u32 postbld_osd1_premult = 0, postbld_osd2_premult = 0;
u32 reg_offset = 2;
u32 shift_line = osd_hw.shift_line;
if (osd_get_chip_type() > MESON_CPU_MAJOR_ID_TM2)
reg_offset = 8;
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_S5 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T7 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5W ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5M ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3X)
postbld_src3_sel = 4;
/* for s5_display, OSDx to din(x+1) */
#ifdef AML_S5_DISPLAY
blend_din_en = 1;
index++;
#endif
if (index == OSD1)
din_reoder_sel = 0x4441;
else if (index == OSD2)
din_reoder_sel = 0x4442;
else if (index == OSD3)
din_reoder_sel = 0x4443;
/* depend on din0_premult_en */
postbld_osd1_premult = 0;
/* depend on din_premult_en bit 4 */
postbld_osd2_premult = 0;
/* osd blend ctrl */
osd_reg_write(VIU_OSD_BLEND_CTRL,
4 << 29|
blend2_premult_en << 27|
din0_byp_blend << 26|
din2_osd_sel << 25|
din3_osd_sel << 24|
blend_din_en << 20|
din_premult_en << 16|
din_reoder_sel);
/* vpp osd1 blend ctrl */
#ifdef AML_S5_DISPLAY
osd_reg_write(OSD1_BLEND_SRC_CTRL,
(postbld_src3_sel & 0xf) << 0 |
(postbld_osd1_premult & 0x1) << 4);
#else
osd_reg_write(OSD1_BLEND_SRC_CTRL,
(0 & 0xf) << 0 |
(0 & 0x1) << 4 |
(postbld_src3_sel & 0xf) << 8 |
(postbld_osd1_premult & 0x1) << 16 |
(1 & 0x1) << 20);
#endif
/* vpp osd2 blend ctrl */
#ifdef AML_S5_DISPLAY
osd_reg_write(OSD2_BLEND_SRC_CTRL,
(postbld_src4_sel & 0xf) << 0 |
(postbld_osd2_premult & 0x1) << 4);
#else
osd_reg_write(OSD2_BLEND_SRC_CTRL,
(0 & 0xf) << 0 |
(0 & 0x1) << 4 |
(postbld_src4_sel & 0xf) << 8 |
(postbld_osd2_premult & 0x1) << 16 |
(1 & 0x1) << 20);
#endif
/* Do later: different format select different dummy_data */
/* used default dummy data */
osd_reg_write(VIU_OSD_BLEND_DUMMY_DATA0,
0x0 << 16 |
0x0 << 8 |
0x0);
/* used default dummy alpha data */
osd_reg_write(VIU_OSD_BLEND_DUMMY_ALPHA,
0x0 << 20 |
0x0 << 11 |
0x0);
width = disp_data->x_end - disp_data->x_start + 1;
height = disp_data->y_end - disp_data->y_start + 1 + shift_line;
/* it is setting for osdx */
osd_reg_write(
VIU_OSD_BLEND_DIN0_SCOPE_H + reg_offset * index,
disp_data->x_end << 16 |
disp_data->x_start);
osd_reg_write(
VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * index,
(disp_data->y_end + shift_line) << 16 |
(disp_data->y_start + shift_line));
if (index == OSD1) {
int i;
for (i = 1; i < 4; i++)
osd_reg_write(
VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
0xffffffff);
} else if (index == OSD2) {
int i = 0;
osd_reg_write(
VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
0xffffffff);
for (i = 2; i < 4; i++)
osd_reg_write(
VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
0xffffffff);
} else if (index == OSD3) {
int i = 0;
for (i = 0; i < 2; i++)
osd_reg_write(VIU_OSD_BLEND_DIN0_SCOPE_V +
reg_offset * i,
0xffffffff);
i = 3;
osd_reg_write(VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
0xffffffff);
}
osd_reg_write(VIU_OSD_BLEND_BLEND0_SIZE,
height << 16 |
width);
osd_reg_write(VIU_OSD_BLEND_BLEND1_SIZE,
height << 16 |
width);
#ifdef AML_S5_DISPLAY
VSYNCOSD_WR_MPEG_REG(OSD_BLEND_DOUT0_SIZE,
height << 16 | width);
VSYNCOSD_WR_MPEG_REG(OSD_BLEND_DOUT1_SIZE,
height << 16 | width);
#endif
#ifndef AML_S5_DISPLAY
osd_reg_write(VPP_OSD1_IN_SIZE,
height << 16 | width);
#endif
if (!is_dolby_enable())
osd_reg_set_bits(DOLBY_PATH_CTRL,
0x3, 2, 2);
/* setting blend scope */
osd_reg_write(VPP_OSD1_BLD_H_SCOPE,
disp_data->x_start << 16 | disp_data->x_end);
osd_reg_write(VPP_OSD1_BLD_V_SCOPE,
disp_data->y_start << 16 | disp_data->y_end);
}
void osd_update_blend(struct pandata_s *disp_data)
{
u32 width, height;
#ifdef AML_S5_DISPLAY
u32 blend_width, blend_height;
#endif
int vmode = -1;
#ifdef CONFIG_AML_VOUT
vmode = vout_get_current_vmode();
#endif
switch (vmode) {
/* case VMODE_LCD: */
case VMODE_480I:
case VMODE_480CVBS:
case VMODE_576I:
case VMODE_576CVBS:
case VMODE_1080I:
case VMODE_1080I_50HZ:
#ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION
case VMODE_1080I_59HZ:
#endif
disp_data->y_start /=2;
disp_data->y_end /= 2;
break;
default:
break;
}
width = disp_data->x_end - disp_data->x_start + 1;
height = disp_data->y_end - disp_data->y_start + 1;
/* setting pi */
if (osd_hw.has_pi) {
if (pi_enable)
osd_reg_set_bits(OSD_PI_BYPASS_EN, 0, 0, 1);
else
osd_reg_set_bits(OSD_PI_BYPASS_EN, 1, 0, 1);
}
/* setting blend regs */
#ifdef AML_S5_DISPLAY
blend_width = osd_hw.free_dst_data[0].x_end - osd_hw.free_dst_data[0].x_start + 1;
blend_height = osd_hw.free_dst_data[0].y_end - osd_hw.free_dst_data[0].y_start + 1;
osd_reg_write(VIU_OSD_BLEND_DIN1_SCOPE_H, (blend_width - 1) << 16);
osd_reg_write(VIU_OSD_BLEND_DIN1_SCOPE_V, (blend_height - 1) << 16);
osd_reg_write(VIU_OSD_BLEND_BLEND0_SIZE,
blend_height << 16 | ALIGN(blend_width, 4));
osd_reg_write(OSD_BLEND_DOUT0_SIZE,
blend_height << 16 | ALIGN(blend_width, 4));
#endif
/* setting blend scope */
osd_reg_write(VPP_OSD1_BLD_H_SCOPE,
disp_data->x_start << 16 | disp_data->x_end);
osd_reg_write(VPP_OSD1_BLD_V_SCOPE,
disp_data->y_start << 16 | disp_data->y_end);
osd_reg_write(VPP_OUT_H_V_SIZE,
width << 16 | height);
}
#endif
static void osd_update_mif_linear_addr(u32 index)
{
u32 line_stride, bpp;
u32 fmt_mode = 0;
u32 osd_blk1_cfg_w4, osd_blk2_cfg_w4, osd_ctrl_stat;
switch (index) {
case 0:
osd_blk1_cfg_w4 = hw_osd_reg_array[0].osd_blk1_cfg_w4;
osd_blk2_cfg_w4 = hw_osd_reg_array[0].osd_blk2_cfg_w4;
osd_ctrl_stat = hw_osd_reg_array[0].osd_ctrl_stat;
break;
case 1:
osd_blk1_cfg_w4 = hw_osd_reg_array[1].osd_blk1_cfg_w4;
osd_blk2_cfg_w4 = hw_osd_reg_array[1].osd_blk2_cfg_w4;
osd_ctrl_stat = hw_osd_reg_array[1].osd_ctrl_stat;
break;
case 2:
osd_blk1_cfg_w4 = hw_osd_reg_array[2].osd_blk1_cfg_w4;
osd_blk2_cfg_w4 = hw_osd_reg_array[2].osd_blk2_cfg_w4;
osd_ctrl_stat = hw_osd_reg_array[2].osd_ctrl_stat;
break;
case 3:
osd_blk1_cfg_w4 = hw_osd_reg_array[3].osd_blk1_cfg_w4;
osd_blk2_cfg_w4 = hw_osd_reg_array[3].osd_blk2_cfg_w4;
osd_ctrl_stat = hw_osd_reg_array[3].osd_ctrl_stat;
break;
default:
osd_blk1_cfg_w4 = hw_osd_reg_array[0].osd_blk1_cfg_w4;
osd_blk2_cfg_w4 = hw_osd_reg_array[0].osd_blk2_cfg_w4;
osd_ctrl_stat = hw_osd_reg_array[0].osd_ctrl_stat;
break;
}
if (osd_hw.color_info[index])
fmt_mode =
osd_hw.color_info[index]->color_index;
bpp = osd_hw.color_info[index]->bpp / 8;
/* 64 bytes align */
line_stride = line_stride_calc
(fmt_mode,
osd_hw.fb_gem[index].width / bpp, 0);
/* set frame addr, 8G addr, need >> 4*/
VSYNCOSD_WR_MPEG_REG(osd_blk1_cfg_w4,
osd_hw.fb_gem[index].addr >> 4);
/* set line stride */
VSYNCOSD_WR_MPEG_REG_BITS(osd_blk2_cfg_w4,
line_stride,
0, 12);
/* used phyic addr */
VSYNCOSD_WR_MPEG_REG_BITS(osd_ctrl_stat,
1, 2, 1);
}
static void set_fb_layout_info(u32 index, u32 fb_len)
{
int i, offset = 0;
if (fb_layout[index].used) {
osd_logi("%s, osd%d is already set\n", __func__, index);
return;
}
for (i = 0; i < OSD_MAX; i++) {
if (fb_layout[i].used)
offset += fb_layout[i].fb_len;
}
fb_layout[index].fb_offset = offset;
fb_layout[index].fb_len = fb_len;
fb_layout[index].used = 1;
}
void clear_fb_layout_info(u32 index)
{
fb_layout[index].fb_offset = 0;
fb_layout[index].fb_len = 0;
fb_layout[index].used = 0;
}
unsigned int get_fb_offset(u32 index)
{
if (fb_layout[index].used)
return fb_layout[index].fb_offset;
osd_loge("%s, osd%d fb_offset is not set\n", __func__, index);
return 0;
}
unsigned int get_fb_len(u32 index)
{
if (fb_layout[index].used)
return fb_layout[index].fb_len;
osd_loge("%s, osd%d fb_len is not set\n", __func__, index);
return 0;
}
#ifdef AML_C3_DISPLAY
static void osd_setting_vout_blend(void)
{
int axis[4] = {};
if (osd_hw.free_dst_data[OSD1].x_end == 0 ||
osd_hw.free_dst_data[OSD1].y_end == 0) {
vout_get_current_axis(axis);
osd_set_window_axis_hw(OSD1, axis[0], axis[1], axis[0] + axis[2] - 1,
axis[1] + axis[3] - 1);
}
VSYNCOSD_WR_MPEG_REG_BITS
(VPU_VOUT_BLD_SRC1_HPOS,
osd_hw.free_dst_data[OSD1].x_start,
0, 13);
VSYNCOSD_WR_MPEG_REG_BITS
(VPU_VOUT_BLD_SRC1_HPOS,
osd_hw.free_dst_data[OSD1].x_end,
16, 13);
VSYNCOSD_WR_MPEG_REG_BITS
(VPU_VOUT_BLD_SRC1_VPOS,
osd_hw.free_dst_data[OSD1].y_start,
0, 13);
VSYNCOSD_WR_MPEG_REG_BITS
(VPU_VOUT_BLD_SRC1_VPOS,
osd_hw.free_dst_data[OSD1].y_end,
16, 13);
}
/* for c3 */
static void osd1_matrix_yuv2rgb(int yuv2rgb)
{
int i;
int mat_conv_en;
int pre_offset[3], post_offset[3];
int mat_coef[15];
int rgb2yuvpre[3] = {0, 0, 0};
int rgb2yuvpos[3] = {64, 512, 512};
int yuv2rgbpre[3] = {-64, -512, -512};
int yuv2rgbpos[3] = {0, 0, 0};
static int matrix_save;
/* matrix coef BT709 */
int rgb2ycbcr[15] = {264, 516, 100, -152, -296, 448,
448, -376, -72, 0, 0, 0, 0, 0, 0};
int ycbcr2rgb[15] = {1197, 0, 1726, 1197, -193, -669,
1197, 2202, 0, 0, 0, 0, 0, 0, 0};
if (matrix_save == yuv2rgb)
return;
switch (yuv2rgb) {
case MATRIX_BYPASS:
mat_conv_en = 0;
break;
case YUV2RGB:
mat_conv_en = 1;
for (i = 0; i < 3; i++) {
pre_offset[i] = yuv2rgbpre[i];
post_offset[i] = yuv2rgbpos[i];
}
for (i = 0; i < 15; i++)
mat_coef[i] = ycbcr2rgb[i];
break;
case RGB2YUV:
mat_conv_en = 1;
for (i = 0; i < 3; i++) {
pre_offset[i] = rgb2yuvpre[i];
post_offset[i] = rgb2yuvpos[i];
}
for (i = 0; i < 15; i++)
mat_coef[i] = rgb2ycbcr[i];
break;
}
matrix_save = yuv2rgb;
if (yuv2rgb != MATRIX_BYPASS) {
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_COEF00_01,
(mat_coef[0] << 16) |
(mat_coef[1] & 0x1FFF));
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_COEF02_10,
(mat_coef[2] << 16) |
(mat_coef[1 * 3 + 0] & 0x1FFF));
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_COEF11_12,
(mat_coef[1 * 3 + 1] << 16) |
(mat_coef[1 * 3 + 2] & 0x1FFF));
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_COEF20_21,
(mat_coef[2 * 3 + 0] << 16) |
(mat_coef[2 * 3 + 1] & 0x1FFF));
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_COEF22,
mat_coef[2 * 3 + 2]);
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_OFFSET0_1,
(post_offset[0] << 16) |
(post_offset[1] & 0xFFF));
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_OFFSET2,
post_offset[2]);
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_PRE_OFFSET0_1,
(pre_offset[0] << 16) |
(pre_offset[1] & 0xFFF));
VSYNCOSD_WR_MPEG_REG
(VOUT_OSD1_CSC_PRE_OFFSET2,
pre_offset[2]);
}
/* vd1_mat_en */
VSYNCOSD_WR_MPEG_REG_BITS
(VOUT_OSD1_CSC_EN_CTRL,
mat_conv_en, 0, 1);
}
#endif
void osd_setup_hw(u32 index,
u32 xoffset,
u32 yoffset,
u32 xres,
u32 yres,
u32 xres_virtual,
u32 yres_virtual,
u32 disp_start_x,
u32 disp_start_y,
u32 disp_end_x,
u32 disp_end_y,
u32 fbmem,
const struct color_bit_define_s *color)
{
struct pandata_s disp_data;
struct pandata_s pan_data;
int update_color_mode = 0;
int update_geometry = 0;
u32 w = (color->bpp * xres_virtual + 7) >> 3;
u32 fb_len;
char cmd[64];
if (osd_hw.osd_ver == OSD_SIMPLE) {
if (index >= OSD2) {
osd_loge("AXG/A4/C3 not support osd2\n");
return ;
}
}
pan_data.x_start = xoffset;
pan_data.y_start = yoffset;
disp_data.x_start = disp_start_x;
disp_data.y_start = disp_start_y;
if (osd_hw.free_scale_enable[OSD1] && index == OSD1) {
if (!(osd_hw.free_scale_mode[OSD1])) {
pan_data.x_end = xoffset + g_vf_visual_width;
pan_data.y_end = yoffset + g_vf_height;
disp_data.x_end = disp_start_x + g_vf_width;
disp_data.y_end = disp_start_y + g_vf_height;
} else {
pan_data.x_end = xoffset + (disp_end_x - disp_start_x);
pan_data.y_end = yoffset + (disp_end_y - disp_start_y);
disp_data.x_end = disp_end_x;
disp_data.y_end = disp_end_y;
}
} else {
pan_data.x_end = xoffset + (disp_end_x - disp_start_x);
pan_data.y_end = yoffset + (disp_end_y - disp_start_y);
if (likely(osd_hw.rotate[index].on_off
&& osd_hw.rotate[index].on_off > 0)) {
disp_data.x_end = disp_start_x + g_rotation_height;
disp_data.y_end = disp_start_y + g_rotation_width;
} else {
disp_data.x_end = disp_end_x;
disp_data.y_end = disp_end_y;
}
}
if (color != osd_hw.color_info[index]) {
update_color_mode = 1;
osd_hw.color_info[index] = color;
}
if (osd_hw.fb_gem[index].addr != fbmem
|| osd_hw.fb_gem[index].width != w
|| osd_hw.fb_gem[index].height != yres_virtual) {
osd_hw.fb_gem[index].addr = fbmem;
osd_hw.fb_gem[index].width = w;
osd_hw.fb_gem[index].height = yres_virtual;
if (osd_hw.osd_ver == OSD_SIMPLE &&
osd_get_chip_type() != MESON_CPU_MAJOR_ID_A4) {
u32 line_stride, fmt_mode, bpp;
bpp = color->bpp/8;
fmt_mode = color->color_index;
line_stride = line_stride_calc(fmt_mode,
osd_hw.fb_gem[index].width / bpp, 1);
VSYNCOSD_WR_MPEG_REG(
hw_osd_reg_array[0].osd_blk1_cfg_w4,
osd_hw.fb_gem[index].addr);
VSYNCOSD_WR_MPEG_REG_BITS(
hw_osd_reg_array[0].osd_blk2_cfg_w4,
line_stride,
0, 12);
} else if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_A4) {
osd_update_mif_linear_addr(OSD1);
} else {
fb_len = fb_gdev.fb_height *
CANVAS_ALIGNED(fb_gdev.fb_width * color->bpp >> 3);
set_fb_layout_info(index, fb_len);
osd_hw.fb_gem[index].addr += get_fb_offset(index);
osd_logd("%s, set osd%d fb_addr:0x%x fb_len:%d\n",
__func__, index,
osd_hw.fb_gem[index].addr, fb_len);
if (osd_hw.mif_linear)
osd_update_mif_linear_addr(index);
#ifdef CONFIG_AML_CANVAS
else
canvas_config(osd_hw.fb_gem[index].canvas_idx,
osd_hw.fb_gem[index].addr,
CANVAS_ALIGNED(osd_hw.fb_gem[index].width),
osd_hw.fb_gem[index].height,
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
#endif
}
snprintf(cmd, sizeof(cmd), "setenv fb_addr 0x%x",
osd_hw.fb_gem[index].addr);
run_command(cmd, 0);
osd_logd("osd[%d] canvas.idx =0x%x\n",
index, osd_hw.fb_gem[index].canvas_idx);
osd_logd("osd[%d] canvas.addr=0x%x\n",
index, osd_hw.fb_gem[index].addr);
osd_logd("osd[%d] canvas.width=%d\n",
index, CANVAS_ALIGNED(osd_hw.fb_gem[index].width));
osd_logd("osd[%d] canvas.height=%d\n",
index, osd_hw.fb_gem[index].height);
}
/* osd blank only control by /sys/class/graphics/fbx/blank */
#if 0
if (osd_hw.enable[index] == DISABLE) {
osd_hw.enable[index] = ENABLE;
add_to_update_list(index, OSD_ENABLE);
}
#endif
if (memcmp(&pan_data, &osd_hw.pandata[index],
sizeof(struct pandata_s)) != 0 ||
memcmp(&disp_data, &osd_hw.dispdata[index],
sizeof(struct pandata_s)) != 0) {
update_geometry = 1;
memcpy(&osd_hw.pandata[index], &pan_data,
sizeof(struct pandata_s));
memcpy(&osd_hw.dispdata[index], &disp_data,
sizeof(struct pandata_s));
}
if (update_color_mode)
add_to_update_list(index, OSD_COLOR_MODE);
if (update_geometry)
add_to_update_list(index, DISP_GEOMETRY);
add_to_update_list(index, DISP_OSD_REVERSE);
#ifdef AML_OSD_HIGH_VERSION
static int is_blend_set;
if (osd_hw.osd_ver == OSD_HIGH_ONE && index < VIU2_OSD1 && !is_blend_set) {
is_blend_set = 1;
osd_setting_default_hwc(index, &disp_data);
}
#endif
osd_wait_vsync_hw();
}
void osd2_setup_hw(u32 index,
u32 xoffset,
u32 yoffset,
u32 xres,
u32 yres,
u32 xres_virtual,
u32 yres_virtual,
u32 disp_start_x,
u32 disp_start_y,
u32 disp_end_x,
u32 disp_end_y,
u32 fbmem,
const struct color_bit_define_s *color)
{
struct pandata_s disp_data;
struct pandata_s pan_data;
int update_color_mode = 0;
int update_geometry = 0;
u32 w = (color->bpp * xres_virtual + 7) >> 3;
if (osd_hw.osd_ver == OSD_SIMPLE) {
if (index >= OSD2) {
osd_loge("AXG not support osd2\n");
return;
}
}
pan_data.x_start = xoffset;
pan_data.y_start = yoffset;
disp_data.x_start = disp_start_x;
disp_data.y_start = disp_start_y;
if (osd_hw.free_scale_enable[OSD1] && index == OSD1) {
if (!(osd_hw.free_scale_mode[OSD1])) {
pan_data.x_end = xoffset + g_vf_visual_width;
pan_data.y_end = yoffset + g_vf_height;
disp_data.x_end = disp_start_x + g_vf_width;
disp_data.y_end = disp_start_y + g_vf_height;
} else {
pan_data.x_end = xoffset + (disp_end_x - disp_start_x);
pan_data.y_end = yoffset + (disp_end_y - disp_start_y);
disp_data.x_end = disp_end_x;
disp_data.y_end = disp_end_y;
}
} else {
pan_data.x_end = xoffset + (disp_end_x - disp_start_x);
pan_data.y_end = yoffset + (disp_end_y - disp_start_y);
if (likely(osd_hw.rotate[index].on_off &&
osd_hw.rotate[index].on_off > 0)) {
disp_data.x_end = disp_start_x + g_rotation_height;
disp_data.y_end = disp_start_y + g_rotation_width;
} else {
disp_data.x_end = disp_end_x;
disp_data.y_end = disp_end_y;
}
}
if (color != osd_hw.color_info[index]) {
update_color_mode = 1;
osd_hw.color_info[index] = color;
}
if (osd_hw.fb_gem[index].addr != fbmem ||
osd_hw.fb_gem[index].width != w ||
osd_hw.fb_gem[index].height != yres_virtual) {
osd_hw.fb_gem[index].addr = fbmem;
osd_hw.fb_gem[index].width = w;
osd_hw.fb_gem[index].height = yres_virtual;
if (osd_hw.osd_ver == OSD_SIMPLE) {
u32 line_stride, fmt_mode, bpp;
bpp = color->bpp / 8;
fmt_mode = color->color_index;
line_stride = line_stride_calc(fmt_mode,
osd_hw.fb_gem[index].width / bpp, 1);
VSYNCOSD_WR_MPEG_REG
(hw_osd_reg_array[0].osd_blk1_cfg_w4,
osd_hw.fb_gem[index].addr);
VSYNCOSD_WR_MPEG_REG_BITS
(hw_osd_reg_array[0].osd_blk2_cfg_w4,
line_stride,
0, 12);
} else {
if (osd_hw.mif_linear) {
if (index >= VIU2_OSD1)
/* for dual logo display */
osd_hw.fb_gem[index].addr +=
fb_gdev.fb_height *
CANVAS_ALIGNED(fb_gdev.fb_width *
color->bpp >> 3);
osd_update_mif_linear_addr(index);
}
}
osd_logd("osd[%d] canvas.idx =0x%x\n",
index, osd_hw.fb_gem[index].canvas_idx);
osd_logd("osd[%d] canvas.addr=0x%x\n",
index, osd_hw.fb_gem[index].addr);
osd_logd("osd[%d] canvas.width=%d\n",
index, CANVAS_ALIGNED(osd_hw.fb_gem[index].width));
osd_logd("osd[%d] canvas.height=%d\n",
index, osd_hw.fb_gem[index].height);
}
/* osd blank only control by /sys/class/graphics/fbx/blank */
if (memcmp(&pan_data, &osd_hw.pandata[index],
sizeof(struct pandata_s)) != 0 ||
memcmp(&disp_data, &osd_hw.dispdata[index],
sizeof(struct pandata_s)) != 0) {
update_geometry = 1;
memcpy(&osd_hw.pandata[index], &pan_data,
sizeof(struct pandata_s));
memcpy(&osd_hw.dispdata[index], &disp_data,
sizeof(struct pandata_s));
}
if (update_color_mode)
add_to_update_list(index, OSD_COLOR_MODE);
if (update_geometry)
add_to_update_list(index, DISP_GEOMETRY);
add_to_update_list(index, DISP_OSD_REVERSE);
osd_wait_vsync_hw();
}
void osd_setpal_hw(u32 index,
unsigned regno,
unsigned red,
unsigned green,
unsigned blue,
unsigned transp
)
{
if (regno < 256) {
u32 pal;
pal = ((red & 0xff) << 24) |
((green & 0xff) << 16) |
((blue & 0xff) << 8) |
(transp & 0xff);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_color_addr +
REG_OFFSET * index,
regno);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_color +
REG_OFFSET * index, pal);
}
}
void osd_get_order_hw(u32 index, u32 *order)
{
*order = osd_hw.order & 0x3;
}
void osd_set_order_hw(u32 index, u32 order)
{
if ((order != OSD_ORDER_01) && (order != OSD_ORDER_10))
return;
osd_hw.order = order;
add_to_update_list(index, OSD_CHANGE_ORDER);
osd_wait_vsync_hw();
}
/* vpu free scale mode */
static void osd_set_free_scale_enable_mode0(u32 index, u32 enable)
{
static struct pandata_s save_disp_data = {0, 0, 0, 0};
#ifdef CONFIG_AM_VIDEO
#ifdef CONFIG_POST_PROCESS_MANAGER
int mode_changed = 0;
if ((index == OSD1) && (osd_hw.free_scale_enable[index] != enable))
mode_changed = 1;
#endif
#endif
osd_logi("osd%d free scale %s\n",
index, enable ? "ENABLE" : "DISABLE");
enable = (enable & 0xffff ? 1 : 0);
osd_hw.free_scale_enable[index] = enable;
if (index == OSD1) {
if (enable) {
osd_vf_need_update = true;
#ifdef CONFIG_AM_VIDEO
if ((osd_hw.free_scale_data[OSD1].x_end > 0)
&& (osd_hw.free_scale_data[OSD1].x_end > 0)) {
vf.width = osd_hw.free_scale_data[index].x_end -
osd_hw.free_scale_data[index].x_start + 1;
vf.height =
osd_hw.free_scale_data[index].y_end -
osd_hw.free_scale_data[index].y_start + 1;
} else {
vf.width = osd_hw.free_scale_width[OSD1];
vf.height = osd_hw.free_scale_height[OSD1];
}
vf.type = (VIDTYPE_NO_VIDEO_ENABLE | VIDTYPE_PROGRESSIVE
| VIDTYPE_VIU_FIELD | VIDTYPE_VSCALE_DISABLE);
vf.ratio_control = DISP_RATIO_FORCECONFIG
| DISP_RATIO_NO_KEEPRATIO;
if (osd_vf_prov_init == 0) {
vf_provider_init(&osd_vf_prov,
PROVIDER_NAME, &osd_vf_provider, NULL);
osd_vf_prov_init = 1;
}
vf_reg_provider(&osd_vf_prov);
memcpy(&save_disp_data, &osd_hw.dispdata[OSD1],
sizeof(struct pandata_s));
g_vf_visual_width =
vf.width - 1 - osd_hw.dispdata[OSD1].x_start;
g_vf_width = vf.width - 1;
g_vf_height = vf.height - 1;
osd_hw.dispdata[OSD1].x_end =
osd_hw.dispdata[OSD1].x_start + vf.width - 1;
osd_hw.dispdata[OSD1].y_end =
osd_hw.dispdata[OSD1].y_start + vf.height - 1;
#endif
osd_set_scan_mode(index);
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
osd_hw.reg[index][OSD_ENABLE].update_func();
} else {
osd_vf_need_update = false;
osd_set_scan_mode(index);
if (save_disp_data.x_end <= save_disp_data.x_start ||
save_disp_data.y_end <= save_disp_data.y_start)
return;
memcpy(&osd_hw.dispdata[OSD1], &save_disp_data,
sizeof(struct pandata_s));
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
osd_hw.reg[index][OSD_ENABLE].update_func();
#ifdef CONFIG_AM_VIDEO
vf_unreg_provider(&osd_vf_prov);
#endif
}
} else {
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
osd_hw.reg[index][OSD_ENABLE].update_func();
}
osd_wait_vsync_hw();
#ifdef CONFIG_AM_VIDEO
#ifdef CONFIG_POST_PROCESS_MANAGER
if (mode_changed) {
/* extern void vf_ppmgr_reset(int type); */
vf_ppmgr_reset(1);
}
#endif
#endif
}
/* osd free scale mode */
static void osd_set_free_scale_enable_mode1(u32 index, u32 enable)
{
unsigned int h_enable = 0;
unsigned int v_enable = 0;
int ret = 0;
h_enable = (enable & 0xffff0000 ? 1 : 0);
v_enable = (enable & 0xffff ? 1 : 0);
osd_hw.free_scale[index].h_enable = h_enable;
osd_hw.free_scale[index].v_enable = v_enable;
osd_hw.free_scale_enable[index] = enable;
if (osd_hw.free_scale_enable[index]) {
if ((osd_hw.free_scale_data[index].x_end > 0) && h_enable) {
osd_hw.free_scale_width[index] =
osd_hw.free_scale_data[index].x_end -
osd_hw.free_scale_data[index].x_start + 1;
}
if ((osd_hw.free_scale_data[index].y_end > 0) && v_enable) {
osd_hw.free_scale_height[index] =
osd_hw.free_scale_data[index].y_end -
osd_hw.free_scale_data[index].y_start + 1;
}
ret = osd_set_scan_mode(index);
if (ret)
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
osd_hw.reg[index][OSD_FREESCALE_COEF].update_func();
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][DISP_FREESCALE_ENABLE].update_func();
osd_hw.reg[index][OSD_ENABLE].update_func();
} else {
ret = osd_set_scan_mode(index);
if (ret)
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][DISP_FREESCALE_ENABLE].update_func();
osd_hw.reg[index][OSD_ENABLE].update_func();
}
#ifdef AML_C3_DISPLAY
osd_setting_vout_blend();
#endif
osd_wait_vsync_hw();
}
void osd_set_free_scale_enable_hw(u32 index, u32 enable)
{
if (osd_hw.free_scale_mode[index])
osd_set_free_scale_enable_mode1(index, enable);
else
osd_set_free_scale_enable_mode0(index, enable);
}
void osd_get_free_scale_enable_hw(u32 index, u32 *free_scale_enable)
{
*free_scale_enable = osd_hw.free_scale_enable[index];
}
void osd_set_free_scale_mode_hw(u32 index, u32 freescale_mode)
{
osd_hw.free_scale_mode[index] = freescale_mode;
}
void osd_get_free_scale_mode_hw(u32 index, u32 *freescale_mode)
{
*freescale_mode = osd_hw.free_scale_mode[index];
}
void osd_set_4k2k_fb_mode_hw(u32 fb_for_4k2k)
{
osd_hw.fb_for_4k2k = fb_for_4k2k;
}
void osd_set_free_scale_width_hw(u32 index, u32 width)
{
osd_hw.free_scale_width[index] = width;
if (osd_hw.free_scale_enable[index] &&
(!osd_hw.free_scale_mode[index])) {
osd_vf_need_update = true;
#ifdef CONFIG_AM_VIDEO
vf.width = osd_hw.free_scale_width[index];
#endif
}
}
void osd_get_free_scale_width_hw(u32 index, u32 *free_scale_width)
{
*free_scale_width = osd_hw.free_scale_width[index];
}
void osd_set_free_scale_height_hw(u32 index, u32 height)
{
osd_hw.free_scale_height[index] = height;
if (osd_hw.free_scale_enable[index] &&
(!osd_hw.free_scale_mode[index])) {
osd_vf_need_update = true;
#ifdef CONFIG_AM_VIDEO
vf.height = osd_hw.free_scale_height[index];
#endif
}
}
void osd_get_free_scale_height_hw(u32 index, u32 *free_scale_height)
{
*free_scale_height = osd_hw.free_scale_height[index];
}
void osd_get_free_scale_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1)
{
*x0 = osd_hw.free_scale_data[index].x_start;
*y0 = osd_hw.free_scale_data[index].y_start;
*x1 = osd_hw.free_scale_data[index].x_end;
*y1 = osd_hw.free_scale_data[index].y_end;
}
void osd_set_free_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1)
{
osd_hw.free_scale_data[index].x_start = x0;
osd_hw.free_scale_data[index].y_start = y0;
osd_hw.free_scale_data[index].x_end = x1;
osd_hw.free_scale_data[index].y_end = y1;
}
void osd_get_scale_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1)
{
*x0 = osd_hw.scaledata[index].x_start;
*x1 = osd_hw.scaledata[index].x_end;
*y0 = osd_hw.scaledata[index].y_start;
*y1 = osd_hw.scaledata[index].y_end;
}
void osd_set_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1)
{
osd_hw.scaledata[index].x_start = x0;
osd_hw.scaledata[index].x_end = x1;
osd_hw.scaledata[index].y_start = y0;
osd_hw.scaledata[index].y_end = y1;
}
void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1)
{
int vmode = -1;
#ifdef CONFIG_AML_VOUT
vmode = vout_get_current_vmode();
#endif
switch (vmode) {
/*case VMODE_LCD:*/
case VMODE_480I:
case VMODE_480CVBS:
case VMODE_576I:
case VMODE_576CVBS:
case VMODE_1080I:
case VMODE_1080I_50HZ:
#ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION
case VMODE_1080I_59HZ:
#endif
*y0 = osd_hw.free_dst_data[index].y_start * 2;
*y1 = osd_hw.free_dst_data[index].y_end * 2;
break;
default:
*y0 = osd_hw.free_dst_data[index].y_start;
*y1 = osd_hw.free_dst_data[index].y_end;
break;
}
*x0 = osd_hw.free_dst_data[index].x_start;
*x1 = osd_hw.free_dst_data[index].x_end;
}
void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1)
{
int vmode = -1;
#ifdef CONFIG_AML_VOUT
vmode = vout_get_current_vmode();
#endif
switch (vmode) {
/* case VMODE_LCD: */
case VMODE_480I:
case VMODE_480CVBS:
case VMODE_576I:
case VMODE_576CVBS:
case VMODE_1080I:
case VMODE_1080I_50HZ:
#ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION
case VMODE_1080I_59HZ:
#endif
osd_hw.free_dst_data[index].y_start = y0 / 2;
osd_hw.free_dst_data[index].y_end = y1 / 2;
break;
default:
osd_hw.free_dst_data[index].y_start = y0;
osd_hw.free_dst_data[index].y_end = y1;
break;
}
osd_hw.free_dst_data[index].x_start = x0;
osd_hw.free_dst_data[index].x_end = x1;
#if defined(CONFIG_FB_OSD2_CURSOR)
osd_hw.cursor_dispdata[index].x_start = x0;
osd_hw.cursor_dispdata[index].x_end = x1;
osd_hw.cursor_dispdata[index].y_start = y0;
osd_hw.cursor_dispdata[index].y_end = y1;
#endif
/* use pi to scale up 2X for w and h */
if (osd_hw.has_pi) {
u32 w = osd_hw.free_dst_data[index].x_end -
osd_hw.free_dst_data[index].x_start + 1;
u32 h = osd_hw.free_dst_data[index].y_end -
osd_hw.free_dst_data[index].y_start + 1;
if ((w > 3840 && h > 2160) || (w > 4096 && h > 2160))
pi_enable = 1;
else
pi_enable = 0;
if (pi_enable) {
osd_hw.free_dst_data[index].x_start /= 2;
osd_hw.free_dst_data[index].x_end =
osd_hw.free_dst_data[index].x_start + w / 2 - 1;
osd_hw.free_dst_data[index].y_start /= 2;
osd_hw.free_dst_data[index].y_end =
osd_hw.free_dst_data[index].y_start + h / 2 - 1;
}
}
}
void osd_get_block_windows_hw(u32 index, u32 *windows)
{
memcpy(windows, osd_hw.block_windows[index],
sizeof(osd_hw.block_windows[index]));
}
void osd_set_block_windows_hw(u32 index, u32 *windows)
{
memcpy(osd_hw.block_windows[index], windows,
sizeof(osd_hw.block_windows[index]));
add_to_update_list(index, DISP_GEOMETRY);
osd_wait_vsync_hw();
}
void osd_get_block_mode_hw(u32 index, u32 *mode)
{
*mode = osd_hw.block_mode[index];
}
void osd_set_block_mode_hw(u32 index, u32 mode)
{
osd_hw.block_mode[index] = mode;
add_to_update_list(index, DISP_GEOMETRY);
osd_wait_vsync_hw();
}
void osd_enable_3d_mode_hw(u32 index, u32 enable)
{
osd_hw.mode_3d[index].enable = enable;
if (enable) {
/* when disable 3d mode ,we should return to standard state. */
osd_hw.mode_3d[index].left_right = OSD_LEFT;
osd_hw.mode_3d[index].l_start = osd_hw.pandata[index].x_start;
osd_hw.mode_3d[index].l_end = (osd_hw.pandata[index].x_end +
osd_hw.pandata[index].x_start) >> 1;
osd_hw.mode_3d[index].r_start = osd_hw.mode_3d[index].l_end + 1;
osd_hw.mode_3d[index].r_end = osd_hw.pandata[index].x_end;
osd_hw.mode_3d[index].origin_scale.h_enable =
osd_hw.scale[index].h_enable;
osd_hw.mode_3d[index].origin_scale.v_enable =
osd_hw.scale[index].v_enable;
osd_set_2x_scale_hw(index, 1, 0);
} else {
osd_set_2x_scale_hw(index,
osd_hw.mode_3d[index].origin_scale.h_enable,
osd_hw.mode_3d[index].origin_scale.v_enable);
}
}
void osd_enable_hw(u32 index, u32 enable)
{
osd_logd("osd[%d] enable: %d\n", index, enable);
osd_hw.enable[index] = enable;
add_to_update_list(index, OSD_ENABLE);
osd_wait_vsync_hw();
}
void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable)
{
osd_logi("osd[%d] set scale, h_scale: %s, v_scale: %s\n",
index, h_scale_enable ? "ENABLE" : "DISABLE",
v_scale_enable ? "ENABLE" : "DISABLE");
osd_logi("osd[%d].scaledata: %d %d %d %d\n",
index,
osd_hw.scaledata[index].x_start,
osd_hw.scaledata[index].x_end,
osd_hw.scaledata[index].y_start,
osd_hw.scaledata[index].y_end);
osd_logi("osd[%d].pandata: %d %d %d %d\n",
index,
osd_hw.pandata[index].x_start,
osd_hw.pandata[index].x_end,
osd_hw.pandata[index].y_start,
osd_hw.pandata[index].y_end);
osd_hw.scale[index].h_enable = h_scale_enable;
osd_hw.scale[index].v_enable = v_scale_enable;
osd_hw.reg[index][DISP_SCALE_ENABLE].update_func();
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_wait_vsync_hw();
}
void osd_set_rotate_angle_hw(u32 index, u32 angle)
{
osd_hw.rotate[index].angle = angle;
add_to_update_list(index, DISP_OSD_ROTATE);
osd_wait_vsync_hw();
}
void osd_get_rotate_angle_hw(u32 index, u32 *angle)
{
*angle = osd_hw.rotate[index].angle;
}
void osd_set_rotate_on_hw(u32 index, u32 on_off)
{
osd_hw.rotate[index].on_off = on_off;
if (on_off) {
g_rotation_width = osd_hw.rotation_pandata[index].x_end -
osd_hw.rotation_pandata[index].x_start;
g_rotation_height = osd_hw.rotation_pandata[index].y_end -
osd_hw.rotation_pandata[index].y_start;
osd_hw.dispdata[index].x_end = osd_hw.dispdata[OSD1].x_start +
g_rotation_height;
osd_hw.dispdata[index].y_end = osd_hw.dispdata[OSD1].y_start +
g_rotation_width;
} else {
#ifndef AML_C3_DISPLAY
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_M8) {
osd_reg_set_mask(VPU_SW_RESET, 1 << 8);
osd_reg_clr_mask(VPU_SW_RESET, 1 << 8);
}
if (index == OSD1) {
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_M8) {
osd_reg_set_mask(VIU_SW_RESET, 1 << 0);
osd_reg_clr_mask(VIU_SW_RESET, 1 << 0);
}
VSYNCOSD_SET_MPEG_REG_MASK(hw_osd_reg_array[0].osd_fifo_ctrl_stat,
1 << 0);
} else {
osd_reg_set_mask(VIU_SW_RESET, 1 << 1);
osd_reg_clr_mask(VIU_SW_RESET, 1 << 1);
VSYNCOSD_SET_MPEG_REG_MASK(hw_osd_reg_array[1].osd_fifo_ctrl_stat,
1 << 0);
}
#else
VSYNCOSD_SET_MPEG_REG_MASK(hw_osd_reg_array[0].osd_fifo_ctrl_stat,
1 << 0);
#endif
}
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][DISP_OSD_ROTATE].update_func();
osd_wait_vsync_hw();
}
void osd_get_rotate_on_hw(u32 index, u32 *on_off)
{
*on_off = osd_hw.rotate[index].on_off;
}
void osd_get_update_state_hw(u32 index, u32 *up_free)
{
if (osd_vf_need_update)
*up_free = 1;
else
*up_free = 0;
}
void osd_set_update_state_hw(u32 index, u32 up_free)
{
if (up_free > 0)
osd_vf_need_update = true;
else
osd_vf_need_update = false;
}
void osd_set_reverse_hw(u32 index, u32 reverse)
{
osd_hw.osd_reverse[index] = reverse;
add_to_update_list(index, DISP_OSD_REVERSE);
osd_wait_vsync_hw();
}
void osd_get_reverse_hw(u32 index, u32 *reverse)
{
*reverse = osd_hw.osd_reverse[index];
}
void osd_set_prot_canvas_hw(u32 index, s32 x_start, s32 y_start, s32 x_end,
s32 y_end)
{
osd_hw.rotation_pandata[index].x_start = x_start;
osd_hw.rotation_pandata[index].y_start = y_start;
osd_hw.rotation_pandata[index].x_end = x_end;
osd_hw.rotation_pandata[index].y_end = y_end;
if (osd_hw.rotate[index].on_off && osd_hw.rotate[index].angle > 0) {
g_rotation_width = osd_hw.rotation_pandata[index].x_end -
osd_hw.rotation_pandata[index].x_start;
g_rotation_height = osd_hw.rotation_pandata[index].y_end -
osd_hw.rotation_pandata[index].y_start;
osd_hw.dispdata[index].x_end = osd_hw.dispdata[OSD1].x_start +
g_rotation_height;
osd_hw.dispdata[index].y_end = osd_hw.dispdata[OSD1].y_start +
g_rotation_width;
osd_hw.reg[index][DISP_GEOMETRY].update_func();
osd_hw.reg[index][OSD_COLOR_MODE].update_func();
}
}
void osd_get_prot_canvas_hw(u32 index, s32 *x_start, s32 *y_start, s32 *x_end,
s32 *y_end)
{
*x_start = osd_hw.rotation_pandata[index].x_start;
*y_start = osd_hw.rotation_pandata[index].y_start;
*x_end = osd_hw.rotation_pandata[index].x_end;
*y_end = osd_hw.rotation_pandata[index].y_end;
}
void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset)
{
long diff_x, diff_y;
#if defined(CONFIG_FB_OSD2_CURSOR)
if (index >= 1)
#else
if (index >= 2)
#endif
return;
if (xoffset != osd_hw.pandata[index].x_start
|| yoffset != osd_hw.pandata[index].y_start) {
diff_x = xoffset - osd_hw.pandata[index].x_start;
diff_y = yoffset - osd_hw.pandata[index].y_start;
osd_hw.pandata[index].x_start += diff_x;
osd_hw.pandata[index].x_end += diff_x;
osd_hw.pandata[index].y_start += diff_y;
osd_hw.pandata[index].y_end += diff_y;
add_to_update_list(index, DISP_GEOMETRY);
osd_wait_vsync_hw();
}
#ifdef CONFIG_AM_FB_EXT
osd_ext_clone_pan(index);
#endif
osd_logd2("offset[%d-%d]x[%d-%d]y[%d-%d]\n",
xoffset, yoffset,
osd_hw.pandata[index].x_start,
osd_hw.pandata[index].x_end,
osd_hw.pandata[index].y_start,
osd_hw.pandata[index].y_end);
}
static void osd_update_disp_scale_enable(u32 index)
{
if (osd_hw.scale[index].h_enable)
VSYNCOSD_SET_MPEG_REG_MASK(hw_osd_reg_array[index].osd_blk0_cfg_w0,
3 << 12);
else
VSYNCOSD_CLR_MPEG_REG_MASK(hw_osd_reg_array[index].osd_blk0_cfg_w0,
3 << 12);
if (osd_hw.scan_mode != SCAN_MODE_INTERLACE) {
if (osd_hw.scale[index].v_enable)
VSYNCOSD_SET_MPEG_REG_MASK(hw_osd_reg_array[index].osd_blk0_cfg_w0,
1 << 14);
else
VSYNCOSD_CLR_MPEG_REG_MASK(hw_osd_reg_array[index].osd_blk0_cfg_w0,
1 << 14);
}
}
static void osd1_update_disp_scale_enable(void)
{
osd_update_disp_scale_enable(OSD1);
}
static void osd2_update_disp_scale_enable(void)
{
osd_update_disp_scale_enable(OSD2);
}
static void viu2_osd1_update_disp_scale_enable(void)
{
osd_update_disp_scale_enable(VIU2_OSD1);
}
static void viu3_osd1_update_disp_scale_enable(void)
{
osd_update_disp_scale_enable(VIU3_OSD1);
}
static void osd_super_scale_enable(u32 index)
{
#ifndef AML_C3_DISPLAY
#ifndef AML_OSD_HIGH_VERSION
u32 data32 = 0x0;
osd_super_scale_mem_power_on();
/* enable osd scaler path */
if (index == OSD1)
data32 = 8;
else {
data32 = 1; /* select osd2 input */
data32 |= 1 << 3; /* enable osd scaler path */
}
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_sc_ctrl0, data32);
/* enable osd super scaler */
data32 = (1 << 0)
| (1 << 1)
| (1 << 2);
VSYNCOSD_WR_MPEG_REG(OSDSR_CTRL_MODE, data32);
/* config osd super scaler setting */
VSYNCOSD_WR_MPEG_REG(OSDSR_UK_GRAD2DDIAG_LIMIT, 0xffffff);
VSYNCOSD_WR_MPEG_REG(OSDSR_UK_GRAD2DADJA_LIMIT, 0xffffff);
VSYNCOSD_WR_MPEG_REG(OSDSR_UK_BST_GAIN, 0x7a7a3a50);
/* config osd super scaler input size */
data32 = (osd_hw.free_scale_height[index] & 0x1fff)
| (osd_hw.free_scale_width[index] & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(OSDSR_HV_SIZEIN, data32);
/* config osd super scaler output size */
data32 = ((osd_hw.free_dst_data[index].x_end & 0xfff) |
(osd_hw.free_dst_data[index].x_start & 0xfff) << 16);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_sco_h_start_end, data32);
data32 = ((osd_hw.free_dst_data[index].y_end & 0xfff) |
(osd_hw.free_dst_data[index].y_start & 0xfff) << 16);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_sco_v_start_end, data32);
#endif
#endif
}
static void osd_super_scale_disable(void)
{
#ifndef AML_C3_DISPLAY
#ifndef AML_OSD_HIGH_VERSION
/* disable osd scaler path */
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_sc_ctrl0, 0);
/* disable osd super scaler */
VSYNCOSD_WR_MPEG_REG(OSDSR_HV_SIZEIN, 0);
VSYNCOSD_WR_MPEG_REG(OSDSR_CTRL_MODE, 0);
osd_super_scale_mem_power_off();
#endif
#endif
}
#define NEW_PPS_PHASE
#ifdef NEW_PPS_PHASE
#define OSD_ZOOM_BITS 20
#define OSD_PHASE_BITS 16
enum osd_f2v_vphase_type_e {
OSD_F2V_IT2IT = 0,
OSD_F2V_IB2IB,
OSD_F2V_IT2IB,
OSD_F2V_IB2IT,
OSD_F2V_P2IT,
OSD_F2V_P2IB,
OSD_F2V_IT2P,
OSD_F2V_IB2P,
OSD_F2V_P2P,
OSD_F2V_TYPE_MAX
};
struct osd_f2v_vphase_s {
u8 rcv_num;
u8 rpt_num;
u16 phase;
};
static void f2v_get_vertical_phase(u32 zoom_ratio,
enum osd_f2v_vphase_type_e type,
u8 bank_length,
struct osd_f2v_vphase_s *vphase)
{
u8 f2v_420_in_pos_luma[OSD_F2V_TYPE_MAX] = {
0, 2, 0, 2, 0, 0, 0, 2, 0};
u8 f2v_420_out_pos[OSD_F2V_TYPE_MAX] = {
0, 2, 2, 0, 0, 2, 0, 0, 0};
s32 offset_in, offset_out;
/* luma */
offset_in = f2v_420_in_pos_luma[type]
<< OSD_PHASE_BITS;
offset_out = (f2v_420_out_pos[type] * zoom_ratio)
>> (OSD_ZOOM_BITS - OSD_PHASE_BITS);
vphase->rcv_num = bank_length;
if (bank_length == 4 || bank_length == 3)
vphase->rpt_num = 1;
else
vphase->rpt_num = 0;
if (offset_in > offset_out) {
vphase->rpt_num = vphase->rpt_num + 1;
vphase->phase =
((4 << OSD_PHASE_BITS) + offset_out - offset_in)
>> 2;
} else {
while ((offset_in + (4 << OSD_PHASE_BITS))
<= offset_out) {
if (vphase->rpt_num == 1)
vphase->rpt_num = 0;
else
vphase->rcv_num++;
offset_in += 4 << OSD_PHASE_BITS;
}
vphase->phase = (offset_out - offset_in) >> 2;
}
}
#endif
static void osd_update_disp_freescale_enable(u32 index, u32 reg_index)
{
u64 hf_phase_step, vf_phase_step;
int src_w, src_h, dst_w, dst_h;
int bot_ini_phase, top_ini_phase;
int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
int vsc_bot_rcv_num = 0, vsc_bot_rpt_p0_num = 0;
int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
int hf_bank_len = 4;
int vf_bank_len = 4;
u32 data32 = 0x0;
u32 shift_line = osd_hw.shift_line;
osd_logi("osd%d_update_disp_freescale_enable\n", index);
if (osd_hw.scale_workaround)
vf_bank_len = 2;
else
vf_bank_len = 4;
#ifndef NEW_PPS_PHASE
if (osd_hw.bot_type == 1) {
vsc_bot_rcv_num = 4;
vsc_bot_rpt_p0_num = 1;
} else if (osd_hw.bot_type == 2) {
vsc_bot_rcv_num = 6;
vsc_bot_rpt_p0_num = 2;
} else if (osd_hw.bot_type == 3) {
vsc_bot_rcv_num = 8;
vsc_bot_rpt_p0_num = 3;
}
vsc_ini_rcv_num = vf_bank_len;
vsc_ini_rpt_p0_num =
(vf_bank_len / 2 - 1) > 0 ? (vf_bank_len / 2 - 1) : 0;
#endif
hsc_ini_rcv_num = hf_bank_len;
hsc_ini_rpt_p0_num = hf_bank_len / 2 - 1;
src_w = osd_hw.free_scale_width[index];
src_h = osd_hw.free_scale_height[index];
dst_w = osd_hw.free_dst_data[index].x_end -
osd_hw.free_dst_data[index].x_start + 1;
dst_h = osd_hw.free_dst_data[index].y_end -
osd_hw.free_dst_data[index].y_start + 1;
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_MG9TV) {
/* super scaler mode */
if (osd_hw.free_scale_mode[index] & 0x2) {
if (osd_hw.free_scale_enable[index])
osd_super_scale_enable(index);
else
osd_super_scale_disable();
remove_from_update_list(index, DISP_FREESCALE_ENABLE);
return;
}
}
/* config osd sc control reg */
data32 = 0x0;
if (osd_hw.free_scale_enable[index]) {
/* enable osd scaler */
if (osd_hw.free_scale_mode[index] & 0x1) {
if (osd_hw.osd_ver == OSD_NORMAL)
data32 |= index; /* select osd1/2 input */
data32 |= 1 << 2; /* enable osd scaler */
data32 |= 1 << 3; /* enable osd scaler path */
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_sc_ctrl0, data32);
}
} else {
/* disable osd scaler path */
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_sc_ctrl0, 0);
}
hf_phase_step = (u64)src_w << 24;
if (dst_w == 0)
dst_w = 1;
do_div(hf_phase_step, dst_w);
if (shift_line) {
vf_phase_step = (u64)(src_h - 1) << 20;
if (dst_h == 0)
dst_h = 1;
do_div(vf_phase_step, dst_h);
} else {
vf_phase_step = (u64)src_h << 20;
if (dst_h == 0)
dst_h = 1;
do_div(vf_phase_step, dst_h);
}
#ifdef NEW_PPS_PHASE
if (osd_hw.field_out_en) {
struct osd_f2v_vphase_s vphase;
f2v_get_vertical_phase(vf_phase_step,
OSD_F2V_P2IT,
vf_bank_len,
&vphase);
vsc_ini_rcv_num = vphase.rcv_num;
vsc_ini_rpt_p0_num = vphase.rpt_num;
top_ini_phase = vphase.phase;
f2v_get_vertical_phase(vf_phase_step,
OSD_F2V_P2IB,
vf_bank_len,
&vphase);
vsc_bot_rcv_num = vphase.rcv_num;
vsc_bot_rpt_p0_num = vphase.rpt_num;
bot_ini_phase = vphase.phase;
} else {
struct osd_f2v_vphase_s vphase;
f2v_get_vertical_phase(vf_phase_step,
OSD_F2V_P2P,
vf_bank_len,
&vphase);
vsc_ini_rcv_num = vphase.rcv_num;
vsc_ini_rpt_p0_num = vphase.rpt_num;
top_ini_phase = vphase.phase;
vsc_bot_rcv_num = 0;
vsc_bot_rpt_p0_num = 0;
bot_ini_phase = 0;
}
#else
if (osd_hw.field_out_en) /* interface output */
bot_ini_phase = ((vf_phase_step / 2) >> 4);
else
bot_ini_phase = 0;
top_ini_phase = 0;
#endif
vf_phase_step = (vf_phase_step << 4);
/* config osd scaler in/out hv size */
if (shift_line) {
vsc_ini_rcv_num++;
if (osd_hw.field_out_en)
vsc_bot_rcv_num++;
}
#ifdef AML_S5_DISPLAY
VSYNCOSD_WR_MPEG_REG
(hw_osd_reg_array[reg_index].osd_proc_in_size,
(src_h << 16) | src_w);
VSYNCOSD_WR_MPEG_REG
(hw_osd_reg_array[reg_index].osd_proc_out_size,
(dst_h << 16) | dst_w);
#endif
data32 = 0x0;
if (osd_hw.free_scale_enable[index]) {
data32 = (((src_h - 1 + shift_line) & 0x1fff)
| ((src_w - 1) & 0x1fff) << 16);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_sci_wh_m1, data32);
data32 = ((osd_hw.free_dst_data[index].x_end & 0xfff) |
(osd_hw.free_dst_data[index].x_start & 0xfff) << 16);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_sco_h_start_end, data32);
data32 = ((osd_hw.free_dst_data[index].y_end & 0xfff) |
(osd_hw.free_dst_data[index].y_start & 0xfff) << 16);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_sco_v_start_end, data32);
}
data32 = 0x0;
if (osd_hw.free_scale[index].v_enable) {
data32 |= (vf_bank_len & 0x7)
| ((vsc_ini_rcv_num & 0xf) << 3)
| ((vsc_ini_rpt_p0_num & 0x3) << 8);
if (osd_hw.field_out_en)
data32 |= ((vsc_bot_rcv_num & 0xf) << 11)
| ((vsc_bot_rpt_p0_num & 0x3) << 16)
| (1 << 23);
if (osd_hw.scale_workaround)
data32 |= 1 << 21;
data32 |= 1 << 24;
if (osd_get_chip_type() >= MESON_CPU_MAJOR_ID_G12B)
data32 |= 1 << 25;
}
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_vsc_ctrl0, data32);
data32 = 0x0;
if (osd_hw.free_scale[index].h_enable) {
data32 |= (hf_bank_len & 0x7)
| ((hsc_ini_rcv_num & 0xf) << 3)
| ((hsc_ini_rpt_p0_num & 0x3) << 8);
data32 |= 1 << 22;
}
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_hsc_ctrl0, data32);
data32 = top_ini_phase;
if (osd_hw.free_scale_enable[index]) {
data32 |= (bot_ini_phase & 0xffff) << 16;
if (osd_hw.field_out_en) {
if (shift_line)
src_h--;
if (src_h == dst_h * 2)
data32 |= 0x80008000;
}
VSYNCOSD_WR_MPEG_REG_BITS(hw_osd_reg_array[reg_index].osd_hsc_phase_step,
hf_phase_step, 0, 28);
VSYNCOSD_WR_MPEG_REG_BITS(hw_osd_reg_array[reg_index].osd_hsc_init_phase,
0, 0, 16);
VSYNCOSD_WR_MPEG_REG_BITS(hw_osd_reg_array[reg_index].osd_vsc_phase_step,
vf_phase_step, 0, 28);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[reg_index].osd_vsc_init_phase, data32);
}
remove_from_update_list(index, DISP_FREESCALE_ENABLE);
}
static void osd1_update_disp_freescale_enable(void)
{
osd_update_disp_freescale_enable(OSD1, OSD1);
}
static void osd2_update_disp_freescale_enable(void)
{
osd_update_disp_freescale_enable(OSD2, OSD1);
}
#ifdef AML_T7_DISPLAY
static void osdx_update_disp_freescale_enable(u32 index)
{
u64 hf_phase_step, vf_phase_step;
int src_w, src_h, dst_w, dst_h;
int bot_ini_phase, top_ini_phase;
int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
int vsc_bot_rcv_num = 0, vsc_bot_rpt_p0_num = 0;
int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
int hf_bank_len = 4;
int vf_bank_len = 4;
u32 data32 = 0x0;
u32 shift_line = osd_hw.shift_line;
int osd_index = -1;
u32 osd_sc_ctrl0 = 0, osd_sci_wh_m1 = 0;
u32 osd_sco_h_start_end = 0, osd_sco_v_start_end = 0;
u32 osd_sco_hsc_ctrl0 = 0, osd_sco_vsc_ctrl0 = 0;
u32 osd_sco_hsc_phase_step = 0, osd_sco_vsc_phase_step = 0;
u32 osd_sco_hsc_ini_phase = 0, osd_sco_vsc_ini_phase = 0;
osd_index = get_osd_layer();
if (osd_index < 0) {
osd_loge("%s: invalid osd_index\n", __func__);
return;
}
if (osd_index < VIU2_OSD1) {
osd_sc_ctrl0 = hw_osd_reg_array[0].osd_sc_ctrl0;
osd_sci_wh_m1 = hw_osd_reg_array[0].osd_sci_wh_m1;
osd_sco_h_start_end = hw_osd_reg_array[0].osd_sco_h_start_end;
osd_sco_v_start_end = hw_osd_reg_array[0].osd_sco_v_start_end;
osd_sco_hsc_ctrl0 = hw_osd_reg_array[0].osd_hsc_ctrl0;
osd_sco_vsc_ctrl0 = hw_osd_reg_array[0].osd_vsc_ctrl0;
osd_sco_hsc_phase_step = hw_osd_reg_array[0].osd_hsc_phase_step;
osd_sco_hsc_ini_phase = hw_osd_reg_array[0].osd_hsc_init_phase;
osd_sco_vsc_phase_step = hw_osd_reg_array[0].osd_vsc_phase_step;
osd_sco_vsc_ini_phase = hw_osd_reg_array[0].osd_vsc_init_phase;
} else if (osd_index == VIU2_OSD1) {
osd_sc_ctrl0 = hw_osd_reg_array[2].osd_sc_ctrl0;
osd_sci_wh_m1 = hw_osd_reg_array[2].osd_sci_wh_m1;
osd_sco_h_start_end = hw_osd_reg_array[2].osd_sco_h_start_end;
osd_sco_v_start_end = hw_osd_reg_array[2].osd_sco_v_start_end;
osd_sco_hsc_ctrl0 = hw_osd_reg_array[2].osd_hsc_ctrl0;
osd_sco_vsc_ctrl0 = hw_osd_reg_array[2].osd_vsc_ctrl0;
osd_sco_hsc_phase_step = hw_osd_reg_array[2].osd_hsc_phase_step;
osd_sco_hsc_ini_phase = hw_osd_reg_array[2].osd_hsc_init_phase;
osd_sco_vsc_phase_step = hw_osd_reg_array[2].osd_vsc_phase_step;
osd_sco_vsc_ini_phase = hw_osd_reg_array[2].osd_vsc_init_phase;
} else if (osd_index == VIU3_OSD1) {
osd_sc_ctrl0 = hw_osd_reg_array[3].osd_sc_ctrl0;
osd_sci_wh_m1 = hw_osd_reg_array[3].osd_sci_wh_m1;
osd_sco_h_start_end = hw_osd_reg_array[3].osd_sco_h_start_end;
osd_sco_v_start_end = hw_osd_reg_array[3].osd_sco_v_start_end;
osd_sco_hsc_ctrl0 = hw_osd_reg_array[3].osd_hsc_ctrl0;
osd_sco_vsc_ctrl0 = hw_osd_reg_array[3].osd_vsc_ctrl0;
osd_sco_hsc_phase_step = hw_osd_reg_array[3].osd_hsc_phase_step;
osd_sco_hsc_ini_phase = hw_osd_reg_array[3].osd_hsc_init_phase;
osd_sco_vsc_phase_step = hw_osd_reg_array[3].osd_vsc_phase_step;
osd_sco_vsc_ini_phase = hw_osd_reg_array[3].osd_vsc_init_phase;
} else {
osd_loge("%s: invalid osd_index\n", __func__);
return;
}
if (osd_hw.scale_workaround)
vf_bank_len = 2;
else
vf_bank_len = 4;
#ifndef NEW_PPS_PHASE
if (osd_hw.bot_type == 1) {
vsc_bot_rcv_num = 4;
vsc_bot_rpt_p0_num = 1;
} else if (osd_hw.bot_type == 2) {
vsc_bot_rcv_num = 6;
vsc_bot_rpt_p0_num = 2;
} else if (osd_hw.bot_type == 3) {
vsc_bot_rcv_num = 8;
vsc_bot_rpt_p0_num = 3;
}
vsc_ini_rcv_num = vf_bank_len;
vsc_ini_rpt_p0_num =
(vf_bank_len / 2 - 1) > 0 ? (vf_bank_len / 2 - 1) : 0;
#endif
hsc_ini_rcv_num = hf_bank_len;
hsc_ini_rpt_p0_num = hf_bank_len / 2 - 1;
src_w = osd_hw.free_scale_width[index];
src_h = osd_hw.free_scale_height[index];
dst_w = osd_hw.free_dst_data[index].x_end -
osd_hw.free_dst_data[index].x_start + 1;
dst_h = osd_hw.free_dst_data[index].y_end -
osd_hw.free_dst_data[index].y_start + 1;
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_MG9TV) {
/* super scaler mode */
if (osd_hw.free_scale_mode[index] & 0x2) {
if (osd_hw.free_scale_enable[index])
osd_super_scale_enable(index);
else
osd_super_scale_disable();
remove_from_update_list(index, DISP_FREESCALE_ENABLE);
return;
}
}
/* config osd sc control reg */
data32 = 0x0;
if (osd_hw.free_scale_enable[index]) {
/* enable osd scaler */
if (osd_hw.free_scale_mode[index] & 0x1) {
data32 |= 1; /* select osd2 input */
data32 |= 1 << 2; /* enable osd scaler */
data32 |= 1 << 3; /* enable osd scaler path */
VSYNCOSD_WR_MPEG_REG(osd_sc_ctrl0, data32);
}
} else {
/* disable osd scaler path */
VSYNCOSD_WR_MPEG_REG(osd_sc_ctrl0, 0);
}
hf_phase_step = (u64)src_w << 24;
if (dst_w == 0)
dst_w = 1;
do_div(hf_phase_step, dst_w);
if (shift_line) {
vf_phase_step = (u64)(src_h - 1) << 20;
if (dst_h == 0)
dst_h = 1;
do_div(vf_phase_step, dst_h);
} else {
vf_phase_step = (u64)src_h << 20;
if (dst_h == 0)
dst_h = 1;
do_div(vf_phase_step, dst_h);
}
#ifdef NEW_PPS_PHASE
if (osd_hw.field_out_en) {
struct osd_f2v_vphase_s vphase;
f2v_get_vertical_phase(vf_phase_step,
OSD_F2V_P2IT,
vf_bank_len,
&vphase);
vsc_ini_rcv_num = vphase.rcv_num;
vsc_ini_rpt_p0_num = vphase.rpt_num;
top_ini_phase = vphase.phase;
f2v_get_vertical_phase(vf_phase_step,
OSD_F2V_P2IB,
vf_bank_len,
&vphase);
vsc_bot_rcv_num = vphase.rcv_num;
vsc_bot_rpt_p0_num = vphase.rpt_num;
bot_ini_phase = vphase.phase;
} else {
struct osd_f2v_vphase_s vphase;
f2v_get_vertical_phase(vf_phase_step,
OSD_F2V_P2P,
vf_bank_len,
&vphase);
vsc_ini_rcv_num = vphase.rcv_num;
vsc_ini_rpt_p0_num = vphase.rpt_num;
top_ini_phase = vphase.phase;
vsc_bot_rcv_num = 0;
vsc_bot_rpt_p0_num = 0;
bot_ini_phase = 0;
}
#else
if (osd_hw.field_out_en) /* interface output */
bot_ini_phase = ((vf_phase_step / 2) >> 4);
else
bot_ini_phase = 0;
top_ini_phase = 0;
#endif
vf_phase_step = (vf_phase_step << 4);
/* config osd scaler in/out hv size */
if (shift_line) {
vsc_ini_rcv_num++;
if (osd_hw.field_out_en)
vsc_bot_rcv_num++;
}
data32 = 0x0;
if (osd_hw.free_scale_enable[index]) {
data32 = (((src_h - 1 + shift_line) & 0x1fff)
| ((src_w - 1) & 0x1fff) << 16);
VSYNCOSD_WR_MPEG_REG(osd_sci_wh_m1, data32);
data32 = ((osd_hw.free_dst_data[index].x_end & 0xfff) |
(osd_hw.free_dst_data[index].x_start & 0xfff) << 16);
VSYNCOSD_WR_MPEG_REG(osd_sco_h_start_end, data32);
data32 = ((osd_hw.free_dst_data[index].y_end & 0xfff) |
(osd_hw.free_dst_data[index].y_start & 0xfff) << 16);
VSYNCOSD_WR_MPEG_REG(osd_sco_v_start_end, data32);
}
data32 = 0x0;
if (osd_hw.free_scale[index].h_enable) {
data32 |= (hf_bank_len & 0x7)
| ((hsc_ini_rcv_num & 0xf) << 3)
| ((hsc_ini_rpt_p0_num & 0x3) << 8);
data32 |= 1 << 22;
}
VSYNCOSD_WR_MPEG_REG(osd_sco_hsc_ctrl0, data32);
data32 = 0x0;
if (osd_hw.free_scale[index].v_enable) {
data32 |= (vf_bank_len & 0x7)
| ((vsc_ini_rcv_num & 0xf) << 3)
| ((vsc_ini_rpt_p0_num & 0x3) << 8);
if (osd_hw.field_out_en) /* interface output */
data32 |= ((vsc_bot_rcv_num & 0xf) << 11)
| ((vsc_bot_rpt_p0_num & 0x3) << 16)
| (1 << 23);
if (osd_hw.scale_workaround)
data32 |= 1 << 21;
data32 |= 1 << 24;
if (osd_get_chip_type() >= MESON_CPU_MAJOR_ID_G12B)
data32 |= 1 << 25;
}
VSYNCOSD_WR_MPEG_REG(osd_sco_vsc_ctrl0, data32);
data32 = top_ini_phase;
if (osd_hw.free_scale_enable[index]) {
data32 |= (bot_ini_phase & 0xffff) << 16;
if (osd_hw.field_out_en) {
if (shift_line)
src_h--;
if (src_h == dst_h * 2)
data32 |= 0x80008000;
}
VSYNCOSD_WR_MPEG_REG_BITS(osd_sco_hsc_phase_step,
hf_phase_step, 0, 28);
VSYNCOSD_WR_MPEG_REG_BITS(osd_sco_hsc_ini_phase, 0, 0, 16);
VSYNCOSD_WR_MPEG_REG_BITS(osd_sco_vsc_phase_step,
vf_phase_step, 0, 28);
VSYNCOSD_WR_MPEG_REG(osd_sco_vsc_ini_phase, data32);
}
if (osd_index == VIU2_OSD1) {
/* hdr in size */
VSYNCOSD_WR_MPEG_REG(OSD3_HDR_IN_SIZE, dst_h << 16 | dst_w);
/* vpp_top1 scope */
VSYNCOSD_WR_MPEG_REG
(VPP1_BLD_DIN1_HSCOPE,
(osd_hw.free_dst_data[index].x_start << 16) |
osd_hw.free_dst_data[index].x_end);
VSYNCOSD_WR_MPEG_REG
(VPP1_BLD_DIN1_VSCOPE,
(osd_hw.free_dst_data[index].y_start << 16) |
osd_hw.free_dst_data[index].y_end);
VSYNCOSD_WR_MPEG_REG(VPP1_BLD_OUT_SIZE, dst_h << 16 | dst_w);
osd_logd2("vpp1 bld scop(%d %d %d %d)\n",
osd_hw.free_dst_data[index].x_start,
osd_hw.free_dst_data[index].x_end,
osd_hw.free_dst_data[index].y_start,
osd_hw.free_dst_data[index].y_end);
} else if (osd_index == VIU3_OSD1) {
/* hdr in size */
VSYNCOSD_WR_MPEG_REG(OSD4_HDR_IN_SIZE, dst_h << 16 | dst_w);
/* vpp_top1 scope */
VSYNCOSD_WR_MPEG_REG
(VPP2_BLD_DIN1_HSCOPE,
(osd_hw.free_dst_data[index].x_start << 16) |
osd_hw.free_dst_data[index].x_end);
VSYNCOSD_WR_MPEG_REG
(VPP2_BLD_DIN1_VSCOPE,
(osd_hw.free_dst_data[index].y_start << 16) |
osd_hw.free_dst_data[index].y_end);
VSYNCOSD_WR_MPEG_REG(VPP2_BLD_OUT_SIZE, dst_h << 16 | dst_w);
osd_logd2("vpp2 bld scop(%d %d %d %d)\n",
osd_hw.free_dst_data[index].x_start,
osd_hw.free_dst_data[index].x_end,
osd_hw.free_dst_data[index].y_start,
osd_hw.free_dst_data[index].y_end);
}
remove_from_update_list(index, DISP_FREESCALE_ENABLE);
}
#endif
static void osd_update_coef(u32 index)
{
int i;
bool need_update_coef = false;
int hf_coef_wren = 1;
int vf_coef_wren = 1;
unsigned int *hf_coef, *vf_coef;
if (osd_hw.scale_workaround) {
if (use_v_filter_mode != 3) {
use_v_filter_mode = 3;
need_update_coef = true;
} else
need_update_coef = false;
} else {
if (use_v_filter_mode != osd_v_filter_mode) {
use_v_filter_mode = osd_v_filter_mode;
need_update_coef = true;
} else
need_update_coef = false;
}
if (need_update_coef) {
vf_coef = filter_table[use_v_filter_mode];
if (vf_coef_wren) {
osd_reg_set_bits(hw_osd_reg_array[index].osd_scale_coef_idx,
0x0000, 0, 9);
for (i = 0; i < 33; i++)
osd_reg_write(hw_osd_reg_array[index].osd_scale_coef, vf_coef[i]);
}
}
need_update_coef = false;
if (use_h_filter_mode != osd_h_filter_mode) {
use_h_filter_mode = osd_h_filter_mode;
need_update_coef = true;
}
hf_coef = filter_table[use_h_filter_mode];
if (need_update_coef) {
if (hf_coef_wren) {
osd_reg_set_bits(hw_osd_reg_array[index].osd_scale_coef_idx,
0x0100, 0, 9);
for (i = 0; i < 33; i++)
osd_reg_write(hw_osd_reg_array[index].osd_scale_coef, hf_coef[i]);
}
}
}
static void osd1_update_coef(void)
{
osd_update_coef(OSD1);
remove_from_update_list(OSD1, OSD_FREESCALE_COEF);
}
static void osd2_update_coef(void)
{
osd_update_coef(OSD1);
remove_from_update_list(OSD2, OSD_FREESCALE_COEF);
}
#ifdef AML_T7_DISPLAY
static void osdx_update_coef(u32 index)
{
int i;
bool need_update_coef = false;
int hf_coef_wren = 1;
int vf_coef_wren = 1;
unsigned int *hf_coef, *vf_coef;
int osd_index = -1;
u32 osd_scale_coef_idx = 0;
u32 osd_scale_coef = 0;
static int osd34_use_v_filter_mode[2] = {-1, -1};
static int osd34_use_h_filter_mode[2] = {-1, -1};
int *use_v_filter_mode;
int *use_h_filter_mode;
osd_index = get_osd_layer();
if (osd_index < 0) {
osd_loge("%s: invalid osd_index\n", __func__);
return;
}
osd_logd2("%s, index:%d\n", __func__, osd_index);
if (osd_index < VIU2_OSD1) {
use_v_filter_mode = &osd34_use_v_filter_mode[0];
use_h_filter_mode = &osd34_use_h_filter_mode[0];
osd_scale_coef_idx = hw_osd_reg_array[0].osd_scale_coef_idx;
osd_scale_coef = hw_osd_reg_array[0].osd_scale_coef;
} else {
if (osd_index == VIU2_OSD1) { /* VIU2_OSD1 */
use_v_filter_mode = &osd34_use_v_filter_mode[0];
use_h_filter_mode = &osd34_use_h_filter_mode[0];
} else { /* VIU3_OSD1 */
use_v_filter_mode = &osd34_use_v_filter_mode[1];
use_h_filter_mode = &osd34_use_h_filter_mode[1];
}
osd_scale_coef_idx = hw_osd_reg_array[index].osd_scale_coef_idx;
osd_scale_coef = hw_osd_reg_array[index].osd_scale_coef;
}
if (osd_hw.scale_workaround) {
if (*use_v_filter_mode != 3) {
*use_v_filter_mode = 3;
need_update_coef = true;
} else {
need_update_coef = false;
}
} else {
if (*use_v_filter_mode != osd_v_filter_mode) {
*use_v_filter_mode = osd_v_filter_mode;
need_update_coef = true;
} else {
need_update_coef = false;
}
}
vf_coef = filter_table[*use_v_filter_mode];
if (need_update_coef) {
if (vf_coef_wren) {
osd_reg_set_bits(osd_scale_coef_idx, 0x0000, 0, 9);
for (i = 0; i < 33; i++)
osd_reg_write(osd_scale_coef, vf_coef[i]);
}
}
need_update_coef = false;
if (*use_h_filter_mode != osd_h_filter_mode) {
*use_h_filter_mode = osd_h_filter_mode;
need_update_coef = true;
}
hf_coef = filter_table[*use_h_filter_mode];
if (need_update_coef) {
if (hf_coef_wren) {
osd_reg_set_bits(osd_scale_coef_idx, 0x0100, 0, 9);
for (i = 0; i < 33; i++)
osd_reg_write(osd_scale_coef, hf_coef[i]);
}
}
remove_from_update_list(index, OSD_FREESCALE_COEF);
}
static void viu2_osd1_update_disp_freescale_enable(void)
{
osdx_update_disp_freescale_enable(VIU2_OSD1);
}
static void viu3_osd1_update_disp_freescale_enable(void)
{
osdx_update_disp_freescale_enable(VIU3_OSD1);
}
static void viu2_osd1_update_coef(void)
{
osdx_update_coef(VIU2_OSD1);
}
static void viu3_osd1_update_coef(void)
{
osdx_update_coef(VIU3_OSD1);
}
#else
static void viu2_osd1_update_disp_freescale_enable(void)
{
/* do nothing */
remove_from_update_list(VIU2_OSD1, DISP_FREESCALE_ENABLE);
}
static void viu3_osd1_update_disp_freescale_enable(void)
{
/* do nothing */
remove_from_update_list(VIU3_OSD1, DISP_FREESCALE_ENABLE);
}
static void viu2_osd1_update_coef(void)
{
osd_update_coef(OSD1);
remove_from_update_list(VIU2_OSD1, OSD_FREESCALE_COEF);
}
static void viu3_osd1_update_coef(void)
{
/* do nothing */
remove_from_update_list(VIU3_OSD1, OSD_FREESCALE_COEF);
}
#endif
static void osd_update_color_mode(u32 index)
{
u32 data32 = 0;
if (osd_hw.color_info[index]) {
data32 = (osd_hw.scan_mode == SCAN_MODE_INTERLACE) ? 2 : 0;
data32 |= VSYNCOSD_RD_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w0)
& 0x30007040;
data32 |= osd_hw.fb_gem[index].canvas_idx << 16;
if (!osd_hw.rotate[index].on_off)
data32 |= OSD_DATA_LITTLE_ENDIAN << 15;
/* after t3x, color matrix rgb565 changed */
if (osd_get_chip_type() >= MESON_CPU_MAJOR_ID_T3X &&
osd_hw.color_info[index]->color_index == 16)
data32 |= 2 << 2;
else
data32 |= osd_hw.color_info[index]->hw_colormat << 2;
if (osd_get_chip_type() < MESON_CPU_MAJOR_ID_GXTVBB) {
if (osd_hw.color_info[index]->color_index
< COLOR_INDEX_YUV_422)
data32 |= 1 << 7; /* yuv enable */
}
/* osd_blk_mode */
data32 |= osd_hw.color_info[index]->hw_blkmode << 8;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w0, data32);
}
remove_from_update_list(index, OSD_COLOR_MODE);
}
static void osd1_update_color_mode(void)
{
osd_update_color_mode(OSD1);
}
static void osd2_update_color_mode(void)
{
osd_update_color_mode(OSD2);
}
static void viu2_osd1_update_color_mode(void)
{
osd_update_color_mode(VIU2_OSD1);
}
static void viu3_osd1_update_color_mode(void)
{
osd_update_color_mode(VIU3_OSD1);
}
#ifndef AML_C3_DISPLAY
static void osd1_update_enable(void)
{
u32 video_enable = 0;
if (osd_hw.free_scale_mode[OSD1]) {
if (osd_hw.enable[OSD1] == ENABLE) {
if (osd_hw.osd_ver <= OSD_NORMAL)
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND | VPP_POSTBLEND_EN);
VSYNCOSD_SET_MPEG_REG_MASK
(hw_osd_reg_array[0].osd_ctrl_stat, 1 << 0);
} else {
VSYNCOSD_CLR_MPEG_REG_MASK
(hw_osd_reg_array[0].osd_ctrl_stat, 1 << 0);
if (osd_hw.osd_ver <= OSD_NORMAL)
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND);
}
} else if (osd_hw.osd_ver <= OSD_NORMAL) {
video_enable |= VSYNCOSD_RD_MPEG_REG(VPP_MISC)&VPP_VD1_PREBLEND;
if (osd_hw.enable[OSD1] == ENABLE) {
if (osd_hw.free_scale_enable[OSD1]) {
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND);
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_PREBLEND
| VPP_VD1_POSTBLEND
| VPP_PREBLEND_EN);
} else {
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_PREBLEND);
if (!video_enable)
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_VD1_POSTBLEND);
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND);
}
} else {
if (osd_hw.free_scale_enable[OSD1])
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_PREBLEND);
else
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND);
}
}
remove_from_update_list(OSD1, OSD_ENABLE);
}
static void osd2_update_enable(void)
{
u32 video_enable = 0;
if (osd_hw.free_scale_mode[OSD2]) {
if (osd_hw.enable[OSD2] == ENABLE)
VSYNCOSD_SET_MPEG_REG_MASK(hw_osd_reg_array[1].osd_ctrl_stat,
1 << 0);
else
VSYNCOSD_CLR_MPEG_REG_MASK(hw_osd_reg_array[1].osd_ctrl_stat,
1 << 0);
/* for older chips than g12a:
* freescale output always on VPP_OSD1_POSTBLEND
* if freescale is enable, VPP_OSD1_POSTBLEND to control OSD1&OSD2
* if freescale is disable, VPP_OSD2_POSTBLEND to control OSD2
*/
if (osd_hw.osd_ver <= OSD_NORMAL) {
if (osd_hw.free_scale_enable[OSD2]) {
if (osd_hw.enable[OSD2] == ENABLE)
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND
| VPP_POSTBLEND_EN);
else
if (!osd_hw.enable[OSD1])
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD1_POSTBLEND);
} else {
if (osd_hw.enable[OSD2] == ENABLE)
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_POSTBLEND
| VPP_POSTBLEND_EN);
else
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_POSTBLEND);
}
}
} else if (osd_hw.osd_ver <= OSD_NORMAL){
video_enable |= VSYNCOSD_RD_MPEG_REG(VPP_MISC)&VPP_VD1_PREBLEND;
if (osd_hw.enable[OSD2] == ENABLE) {
if (osd_hw.free_scale_enable[OSD2]) {
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_POSTBLEND);
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_PREBLEND
| VPP_VD1_POSTBLEND);
} else {
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_PREBLEND);
if (!video_enable)
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_VD1_POSTBLEND);
VSYNCOSD_SET_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_POSTBLEND);
}
} else {
if (osd_hw.free_scale_enable[OSD2])
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_PREBLEND);
else
VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC,
VPP_OSD2_POSTBLEND);
}
}
remove_from_update_list(OSD2, OSD_ENABLE);
}
#endif
static void osd_update_enable(u32 index)
{
if (osd_hw.free_scale_mode[index]) {
if (osd_hw.enable[index] == ENABLE) {
VSYNCOSD_SET_MPEG_REG_MASK
(hw_osd_reg_array[index].osd_ctrl_stat,
1 << 0);
#ifdef AML_C3_DISPLAY
VSYNCOSD_WR_MPEG_REG_BITS(hw_osd_vout_blend_reg.vpu_vout_blend_ctrl,
2, 0, 2);
#endif
} else {
VSYNCOSD_CLR_MPEG_REG_MASK
(hw_osd_reg_array[index].osd_ctrl_stat,
1 << 0);
#ifdef AML_C3_DISPLAY
VSYNCOSD_WR_MPEG_REG_BITS(hw_osd_vout_blend_reg.vpu_vout_blend_ctrl,
0, 0, 2);
#endif
}
}
remove_from_update_list(index, OSD_ENABLE);
}
#ifdef AML_C3_DISPLAY
static void osd1_update_enable(void)
{
osd_update_enable(OSD1);
}
static void osd2_update_enable(void)
{
remove_from_update_list(OSD2, OSD_ENABLE);
}
int test_for_c3(u32 osd_index, u32 fb_data)
{
/*C3 slt test by probe,*/
u32 probe_data = 0;
u32 r_fb = (fb_data & 0xf800) >> 11;
u32 g_fb = (fb_data & 0x07e0) >> 5;
u32 b_fb = fb_data & 0x001f;
u32 r_probe, g_probe, b_probe;
if (fb_gdev.gdfBytesPP != 2) {
osd_loge("%d bit/pixel mode1, not support now\n",
fb_gdev.gdfBytesPP);
return -1;
}
VSYNCOSD_WR_MPEG_REG(VPU_VOUT_PROB_CTRL, 0x14);
VSYNCOSD_WR_MPEG_REG(VPU_VOUT_PROB_SIZE,
(osd_hw.free_dst_data[OSD1].x_end + 1) << 16
| (osd_hw.free_dst_data[OSD1].y_end + 1));
VSYNCOSD_WR_MPEG_REG(VPU_VOUT_PROB_POS, 0x00640064);
probe_data = VSYNCOSD_RD_MPEG_REG(VPU_VOUT_RO_PROB);
r_probe = (probe_data & 0x3ff00000) >> 25;
g_probe = (probe_data & 0xffc00) >> 14;
b_probe = (probe_data & 0x3ff) >> 5;
if (r_fb == r_probe && g_fb == g_probe && b_fb == b_probe) {
osd_logi("=== osd%d, osd_rma_test pass. ===\n", osd_index);
return 0;
}
osd_loge("=== osd%d, osd_rma_test failed. ===\n", osd_index);
osd_loge("fb_data = 0x%x probe_data = 0x%x\n", fb_data, probe_data);
printf("r_fb = %x r_probe = %x\n", r_fb, r_probe);
printf("g_fb = %x g_probe = %x\n", g_fb, g_probe);
printf("b_fb = %x b_probe = %x\n", b_fb, b_probe);
return -1;
}
#endif
static void viu2_osd1_update_enable(void)
{
osd_update_enable(VIU2_OSD1);
}
static void viu3_osd1_update_enable(void)
{
osd_update_enable(VIU3_OSD1);
}
static void osd_update_disp_osd_reverse(u32 index)
{
u32 val = 0;
switch (osd_hw.osd_reverse[index]) {
case REVERSE_XY:
val = 3;
break;
case REVERSE_X:
val = 1;
break;
case REVERSE_Y:
val = 2;
break;
default:
val = REVERSE_NONE;
break;
}
VSYNCOSD_WR_MPEG_REG_BITS(hw_osd_reg_array[index].osd_blk0_cfg_w0,
val, 28, 2);
remove_from_update_list(index, DISP_OSD_REVERSE);
}
static void osd1_update_disp_osd_reverse(void)
{
osd_update_disp_osd_reverse(OSD1);
}
static void osd2_update_disp_osd_reverse(void)
{
osd_update_disp_osd_reverse(OSD2);
}
static void viu2_osd1_update_disp_osd_reverse(void)
{
osd_update_disp_osd_reverse(VIU2_OSD1);
}
static void viu3_osd1_update_disp_osd_reverse(void)
{
osd_update_disp_osd_reverse(VIU3_OSD1);
}
static void osd1_update_disp_osd_rotate(void)
{
remove_from_update_list(OSD1, DISP_OSD_ROTATE);
}
static void osd2_update_disp_osd_rotate(void)
{
remove_from_update_list(OSD2, DISP_OSD_ROTATE);
}
static void viu2_osd1_update_disp_osd_rotate(void)
{
/* do nothing*/
remove_from_update_list(VIU2_OSD1, DISP_OSD_ROTATE);
}
static void viu3_osd1_update_disp_osd_rotate(void)
{
/* do nothing*/
remove_from_update_list(VIU3_OSD1, DISP_OSD_ROTATE);
}
static void osd_update_color_key(u32 index)
{
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_tcolor_ag0,
osd_hw.color_key[index]);
remove_from_update_list(index, OSD_COLOR_KEY);
}
static void osd1_update_color_key(void)
{
osd_update_color_key(OSD1);
}
static void osd2_update_color_key(void)
{
osd_update_color_key(OSD2);
}
static void viu2_osd1_update_color_key(void)
{
osd_update_color_key(VIU2_OSD1);
}
static void viu3_osd1_update_color_key(void)
{
osd_update_color_key(VIU3_OSD1);
}
static void osd_update_color_key_enable(u32 index)
{
u32 data32;
data32 = VSYNCOSD_RD_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w0);
data32 &= ~(1 << 6);
data32 |= (osd_hw.color_key_enable[index] << 6);
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w0, data32);
remove_from_update_list(index, OSD_COLOR_KEY_ENABLE);
}
static void osd1_update_color_key_enable(void)
{
osd_update_color_key_enable(OSD1);
}
static void osd2_update_color_key_enable(void)
{
osd_update_color_key_enable(OSD2);
}
static void viu2_osd1_update_color_key_enable(void)
{
osd_update_color_key_enable(VIU2_OSD1);
}
static void viu3_osd1_update_color_key_enable(void)
{
osd_update_color_key_enable(VIU3_OSD1);
}
static void osd_update_gbl_alpha(u32 index)
{
u32 data32;
data32 = VSYNCOSD_RD_MPEG_REG(hw_osd_reg_array[index].osd_ctrl_stat);
data32 &= ~(0x1ff << 12);
data32 |= osd_hw.gbl_alpha[index] << 12;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_ctrl_stat, data32);
remove_from_update_list(index, OSD_GBL_ALPHA);
}
static void osd1_update_gbl_alpha(void)
{
osd_update_gbl_alpha(OSD1);
}
static void osd2_update_gbl_alpha(void)
{
osd_update_gbl_alpha(OSD2);
}
static void viu2_osd1_update_gbl_alpha(void)
{
osd_update_gbl_alpha(VIU2_OSD1);
}
static void viu3_osd1_update_gbl_alpha(void)
{
osd_update_gbl_alpha(VIU3_OSD1);
}
#ifdef AML_C3_DISPLAY
static void osd2_update_order(void)
{
remove_from_update_list(OSD2, OSD_CHANGE_ORDER);
}
static void osd1_update_order(void)
{
remove_from_update_list(OSD1, OSD_CHANGE_ORDER);
}
#else
static void osd2_update_order(void)
{
switch (osd_hw.order) {
case OSD_ORDER_01:
osd_reg_clr_mask(VPP_MISC, VPP_POST_FG_OSD2 | VPP_PRE_FG_OSD2);
break;
case OSD_ORDER_10:
osd_reg_set_mask(VPP_MISC, VPP_POST_FG_OSD2 | VPP_PRE_FG_OSD2);
break;
default:
break;
}
remove_from_update_list(OSD2, OSD_CHANGE_ORDER);
}
static void osd1_update_order(void)
{
switch (osd_hw.order) {
case OSD_ORDER_01:
osd_reg_clr_mask(VPP_MISC, VPP_POST_FG_OSD2 | VPP_PRE_FG_OSD2);
break;
case OSD_ORDER_10:
osd_reg_set_mask(VPP_MISC, VPP_POST_FG_OSD2 | VPP_PRE_FG_OSD2);
break;
default:
break;
}
remove_from_update_list(OSD1, OSD_CHANGE_ORDER);
}
#endif
static void viu2_osd1_update_order(void)
{
/* do nothing */
remove_from_update_list(VIU2_OSD1, OSD_CHANGE_ORDER);
}
static void viu3_osd1_update_order(void)
{
/* do nothing */
remove_from_update_list(VIU3_OSD1, OSD_CHANGE_ORDER);
}
static void osd1_2x_scale_update_geometry(void)
{
u32 data32;
data32 = (osd_hw.scaledata[OSD1].x_start & 0x1fff) |
(osd_hw.scaledata[OSD1].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w1, data32);
data32 = ((osd_hw.scaledata[OSD1].y_start
+ osd_hw.pandata[OSD1].y_start) & 0x1fff)
| ((osd_hw.scaledata[OSD1].y_end
+ osd_hw.pandata[OSD1].y_start) & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w2, data32);
/* adjust display x-axis */
if (osd_hw.scale[OSD1].h_enable) {
data32 = (osd_hw.dispdata[OSD1].x_start & 0xfff)
| ((osd_hw.dispdata[OSD1].x_start
+ (osd_hw.scaledata[OSD1].x_end
- osd_hw.scaledata[OSD1].x_start) * 2 + 1)
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w3, data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE) {
data32 = ((osd_hw.dispdata[OSD1].y_start >> 1) & 0xfff)
| (((((osd_hw.dispdata[OSD1].y_start
+ (osd_hw.scaledata[OSD1].y_end
- osd_hw.scaledata[OSD1].y_start) * 2)
+ 1) >> 1) - 1) & 0xfff) << 16;
} else {
data32 = (osd_hw.dispdata[OSD1].y_start & 0xfff)
| (((osd_hw.dispdata[OSD1].y_start
+ (osd_hw.scaledata[OSD1].y_end
- osd_hw.scaledata[OSD1].y_start) * 2))
& 0xfff) << 16;
}
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w4, data32);
}
/* adjust display y-axis */
if (osd_hw.scale[OSD1].v_enable) {
data32 = (osd_hw.dispdata[OSD1].x_start & 0xfff)
| ((osd_hw.dispdata[OSD1].x_start
+ (osd_hw.scaledata[OSD1].x_end
- osd_hw.scaledata[OSD1].x_start) * 2 + 1)
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w3, data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE) {
data32 = ((osd_hw.dispdata[OSD1].y_start >> 1) & 0xfff)
| (((((osd_hw.dispdata[OSD1].y_start
+ (osd_hw.scaledata[OSD1].y_end
- osd_hw.scaledata[OSD1].y_start) * 2)
+ 1) >> 1) - 1) & 0xfff) << 16;
} else {
data32 = (osd_hw.dispdata[OSD1].y_start & 0xfff)
| (((osd_hw.dispdata[OSD1].y_start
+ (osd_hw.scaledata[OSD1].y_end
- osd_hw.scaledata[OSD1].y_start) * 2))
& 0xfff) << 16;
}
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w4, data32);
}
}
static void osd1_basic_update_disp_geometry(void)
{
u32 data32;
if (osd_get_chip_type() >= MESON_CPU_MAJOR_ID_M8) {
data32 = (osd_hw.dispdata[OSD1].x_start & 0xfff)
| (osd_hw.dispdata[OSD1].x_end & 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w3, data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE)
data32 = ((osd_hw.dispdata[OSD1].y_start >> 1) & 0xfff)
| ((((osd_hw.dispdata[OSD1].y_end + 1)
>> 1) - 1) & 0xfff) << 16;
else
data32 = (osd_hw.dispdata[OSD1].y_start & 0xfff)
| (osd_hw.dispdata[OSD1].y_end
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w4, data32);
} else {
if (osd_hw.free_scale_mode[OSD1] == 0) {
if (osd_hw.free_scale_enable[OSD1] == 1) {
data32 = (osd_hw.free_scale_data[OSD1].x_start
& 0xfff)
| (osd_hw.free_scale_data[OSD1].x_end
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w3,
data32);
data32 = (osd_hw.free_scale_data[OSD1].y_start
& 0xfff)
| (osd_hw.free_scale_data[OSD1].y_end
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w4,
data32);
} else {
data32 = (osd_hw.dispdata[OSD1].x_start
& 0xfff)
| (osd_hw.dispdata[OSD1].x_end
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w3,
data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE)
data32 = ((osd_hw.dispdata[OSD1].y_start
>> 1) & 0xfff)
| ((((osd_hw.dispdata[OSD1].y_end
+ 1) >> 1) - 1)
& 0xfff) << 16;
else
data32 = (osd_hw.dispdata[OSD1].y_start
& 0xfff)
| (osd_hw.dispdata[OSD1].y_end
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w4,
data32);
}
} else {
data32 = (osd_hw.dispdata[OSD1].x_start & 0xfff)
| (osd_hw.dispdata[OSD1].x_end & 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w3, data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE)
data32 = ((osd_hw.dispdata[OSD1].y_start >> 1)
& 0xfff)
| ((((osd_hw.dispdata[OSD1].y_end + 1)
>> 1) - 1) & 0xfff) << 16;
else
data32 = (osd_hw.dispdata[OSD1].y_start & 0xfff)
| (osd_hw.dispdata[OSD1].y_end
& 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w4, data32);
}
}
/* enable osd 2x scale */
if (osd_hw.scale[OSD1].h_enable || osd_hw.scale[OSD1].v_enable)
osd1_2x_scale_update_geometry();
else if (osd_hw.free_scale_enable[OSD1]
&& (osd_hw.free_scale_data[OSD1].x_end > 0)
&& (osd_hw.free_scale_data[OSD1].y_end > 0)
&& (!osd_hw.rotate[OSD1].on_off)) {
/* enable osd free scale */
data32 = (osd_hw.free_scale_data[OSD1].x_start & 0x1fff) |
(osd_hw.free_scale_data[OSD1].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w1, data32);
data32 = ((osd_hw.free_scale_data[OSD1].y_start
+ osd_hw.pandata[OSD1].y_start) & 0x1fff)
| ((osd_hw.free_scale_data[OSD1].y_end
+ osd_hw.pandata[OSD1].y_start) & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w2, data32);
} else if (osd_hw.free_scale_enable[OSD1]
&& (osd_hw.free_scale_data[OSD1].x_end > 0)
&& (osd_hw.free_scale_data[OSD1].y_end > 0)
&& (osd_hw.rotate[OSD1].on_off
&& osd_hw.rotate[OSD1].angle > 0)) {
data32 = (osd_hw.rotation_pandata[OSD1].x_start & 0x1fff) |
(osd_hw.rotation_pandata[OSD1].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w1, data32);
data32 = ((osd_hw.rotation_pandata[OSD1].y_start
+ osd_hw.pandata[OSD1].y_start) & 0x1fff)
| ((osd_hw.rotation_pandata[OSD1].y_end
+ osd_hw.pandata[OSD1].y_start) & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w2, data32);
#ifndef AML_OSD_HIGH_VERSION
#ifndef AML_C3_DISPLAY
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_M8)
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_Y_START_END, data32);
#endif
#endif
} else if (osd_hw.rotate[OSD1].on_off
&& osd_hw.rotate[OSD1].angle > 0) {
/* enable osd rotation */
data32 = (osd_hw.rotation_pandata[OSD1].x_start & 0x1fff) |
(osd_hw.rotation_pandata[OSD1].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w1, data32);
data32 = ((osd_hw.rotation_pandata[OSD1].y_start
+ osd_hw.pandata[OSD1].y_start) & 0x1fff)
| ((osd_hw.rotation_pandata[OSD1].y_end
+ osd_hw.pandata[OSD1].y_start) & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w2, data32);
#ifndef AML_OSD_HIGH_VERSION
#ifndef AML_C3_DISPLAY
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_M8)
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_Y_START_END, data32);
#endif
#endif
} else {
/* normal mode */
data32 = (osd_hw.pandata[OSD1].x_start & 0x1fff)
| (osd_hw.pandata[OSD1].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w1, data32);
data32 = (osd_hw.pandata[OSD1].y_start & 0x1fff)
| (osd_hw.pandata[OSD1].y_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[0].osd_blk0_cfg_w2, data32);
}
}
static void osd1_update_disp_geometry(void)
{
osd1_basic_update_disp_geometry();
remove_from_update_list(OSD1, DISP_GEOMETRY);
}
static void osd_update_disp_geometry(u32 index)
{
u32 data32;
data32 = (osd_hw.dispdata[index].x_start & 0xfff)
| (osd_hw.dispdata[index].x_end & 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w3, data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE)
data32 = ((osd_hw.dispdata[index].y_start >> 1) & 0xfff)
| ((((osd_hw.dispdata[index].y_end + 1) >> 1) - 1)
& 0xfff) << 16;
else
data32 = (osd_hw.dispdata[index].y_start & 0xfff)
| (osd_hw.dispdata[index].y_end & 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w4, data32);
if (osd_hw.scale[index].h_enable || osd_hw.scale[index].v_enable) {
#if defined(CONFIG_FB_OSD2_CURSOR)
data32 = (osd_hw.pandata[index].x_start & 0x1fff)
| (osd_hw.pandata[index].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
data32 = (osd_hw.pandata[index].y_start & 0x1fff)
| (osd_hw.pandata[index].y_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w2, data32);
#else
data32 = (osd_hw.scaledata[index].x_start & 0x1fff) |
(osd_hw.scaledata[index].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
data32 = ((osd_hw.scaledata[index].y_start
+ osd_hw.pandata[index].y_start) & 0x1fff)
| ((osd_hw.scaledata[index].y_end
+ osd_hw.pandata[index].y_start) & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w2, data32);
#endif
} else if (osd_hw.free_scale_enable[index] &&
(osd_hw.free_scale_data[index].x_end > 0) &&
(osd_hw.free_scale_data[index].y_end > 0)) {
/* enable osd free scale */
data32 = (osd_hw.free_scale_data[index].x_start & 0x1fff)
| (osd_hw.free_scale_data[index].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
data32 = ((osd_hw.free_scale_data[index].y_start
+ osd_hw.pandata[index].y_start) & 0x1fff)
| ((osd_hw.free_scale_data[index].y_end
+ osd_hw.pandata[index].y_start) & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w2, data32);
} else {
data32 = (osd_hw.pandata[index].x_start & 0x1fff)
| (osd_hw.pandata[index].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
data32 = (osd_hw.pandata[index].y_start & 0x1fff)
| (osd_hw.pandata[index].y_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w2, data32);
}
remove_from_update_list(index, DISP_GEOMETRY);
}
static void osd2_update_disp_geometry(void)
{
osd_update_disp_geometry(OSD2);
}
#ifdef AML_S5_DISPLAY
static void wr_slice_vpost(int reg_addr, int val, int slice_idx)
{
u32 reg_offset;
u32 reg_addr_tmp;
reg_offset = slice_idx == 0 ? 0 :
slice_idx == 1 ? 0x100 :
slice_idx == 2 ? 0x700 : 0x1900;
reg_addr_tmp = reg_addr + reg_offset * 4;
VSYNCOSD_WR_MPEG_REG(reg_addr_tmp, val);
};
static void wr_reg_bits_slice_vpost(int reg_addr, int val, int start, int len, int slice_idx)
{
u32 reg_offset;
u32 reg_addr_tmp;
reg_offset = slice_idx == 0 ? 0 :
slice_idx == 1 ? 0x100 :
slice_idx == 2 ? 0x700 : 0x1900;
reg_addr_tmp = reg_addr + reg_offset * 4;
VSYNCOSD_WR_MPEG_REG_BITS(reg_addr_tmp, val, start, len);
};
/* hw reg info set */
void vpp_post_blend_set(u32 vpp_index,
struct vpp_post_blend_s *vpp_blend)
{
/* setting blend scope */
VSYNCOSD_WR_MPEG_REG(VPP_POSTBLND_H_V_SIZE,
vpp_blend->bld_out_w | vpp_blend->bld_out_h << 16);
VSYNCOSD_WR_MPEG_REG(VPP_POST_BLEND_BLEND_DUMMY_DATA,
vpp_blend->bld_dummy_data);
VSYNCOSD_WR_MPEG_REG_BITS(VPP_POST_BLEND_DUMMY_ALPHA,
0x100 | 0x000 << 16, 0, 32);
// blend0_dummy_alpha|blend1_dummy_alpha<<16
VSYNCOSD_WR_MPEG_REG_BITS(VPP_POST_BLEND_DUMMY_ALPHA1,
0x000 | 0x000 << 16, 0, 32);
// blend2_dummy_alpha|blend3_dummy_alpha<<16
VSYNCOSD_WR_MPEG_REG_BITS(VPP_POSTBLND_CTRL,
vpp_blend->bld_out_en, 8, 1);
osd_logd2("%s: vpp_postblnd_h_v_size=%x\n",
__func__, vpp_blend->bld_out_w | vpp_blend->bld_out_h << 16);
}
void vpp_post_slice_set(u32 vpp_index,
struct vpp_post_s *vpp_post)
{
u32 slice_set;
/* 2ppc2slice overlap size */
VSYNCOSD_WR_MPEG_REG_BITS(VPP_POSTBLND_CTRL,
vpp_post->overlap_hsize, 0, 8);
/* slice mode */
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OBUF_RAM_CTRL,
vpp_post->slice_num - 1, 0, 2);
/* default = 0, 0: 4ppc to 4slice
* 1: 4ppc to 2slice
* 2: 4ppc to 1slice
* 3: disable
*/
switch (vpp_post->slice_num) {
case 1:
slice_set = 2;
break;
case 2:
slice_set = 1;
break;
case 4:
slice_set = 0;
break;
default:
slice_set = 3;
break;
}
VSYNCOSD_WR_MPEG_REG_BITS(VPP_4P4S_CTRL, slice_set, 0, 2);
VSYNCOSD_WR_MPEG_REG_BITS(VPP_4S4P_CTRL, slice_set, 0, 2);
osd_logd2("%s: vpp_4p4s_ctrl=%x\n",
__func__, slice_set);
}
void vpp_vd1_hwin_set(u32 vpp_index,
struct vpp_post_s *vpp_post)
{
u32 vd1_win_in_hsize = 0;
if (vpp_post->vd1_hwin.vd1_hwin_en) {
vd1_win_in_hsize = (vpp_post->vd1_hwin.vd1_hwin_in_hsize +
SLICE_NUM - 1) / SLICE_NUM;
VSYNCOSD_WR_MPEG_REG(VPP_POST_VD1_WIN_CUT_CTRL,
vpp_post->vd1_hwin.vd1_hwin_en << 31 |
vd1_win_in_hsize);
osd_logd2("%s: vpp_post_vd1_win_cut_ctrl:vd1_win_in_hsize=%d\n",
__func__, vd1_win_in_hsize);
} else {
VSYNCOSD_WR_MPEG_REG(VPP_POST_VD1_WIN_CUT_CTRL, 0);
}
}
void vpp_post_proc_set(u32 vpp_index,
struct vpp_post_s *vpp_post)
{
struct vpp_post_proc_s *vpp_post_proc = NULL;
struct vpp_post_proc_slice_s *vpp_post_proc_slice = NULL;
struct vpp_post_proc_hwin_s *vpp_post_proc_hwin = NULL;
u32 slice_num;
int i;
vpp_post_proc = &vpp_post->vpp_post_proc;
vpp_post_proc_slice = &vpp_post_proc->vpp_post_proc_slice;
vpp_post_proc_hwin = &vpp_post_proc->vpp_post_proc_hwin;
slice_num = vpp_post->slice_num;
for (i = 0; i < slice_num; i++) {
wr_slice_vpost(VPP_OUT_H_V_SIZE,
vpp_post_proc_slice->hsize[i] << 16 |
vpp_post_proc_slice->vsize[i], i);
wr_reg_bits_slice_vpost(VPP_OFIFO_SIZE,
0x800, 0, 14, i);
/* slice hwin deal */
wr_reg_bits_slice_vpost(VPP_SLC_DEAL_CTRL,
vpp_post_proc_hwin->hwin_en[i], 3, 1, i);
wr_slice_vpost(VPP_HWIN_SIZE,
vpp_post_proc_hwin->hwin_end[i] << 16 |
vpp_post_proc_hwin->hwin_bgn[i], i);
wr_reg_bits_slice_vpost(VPP_ALIGN_FIFO_SIZE,
vpp_post_proc->align_fifo_size[i], 0, 14, i);
/* todo: for other unit bypass handle */
osd_logd2("%s: vpp_out_h_v_size=%x\n",
__func__, vpp_post_proc_slice->hsize[i] << 16 |
vpp_post_proc_slice->vsize[i]);
osd_logd2("%s: vpp_hwin_size=%x\n",
__func__, vpp_post_proc_hwin->hwin_end[i] << 16 |
vpp_post_proc_hwin->hwin_bgn[i]);
}
}
void vpp_post_padding_set(u32 vpp_index,
struct vpp_post_s *vpp_post)
{
if (vpp_post->vpp_post_pad.vpp_post_pad_en) {
/* reg_pad_hsize */
VSYNCOSD_WR_MPEG_REG(VPP_POST_PAD_HSIZE,
(vpp_post->vpp_post_pad.vpp_post_pad_hsize) << 0);
VSYNCOSD_WR_MPEG_REG(VPP_POST_PAD_CTRL,
vpp_post->vpp_post_pad.vpp_post_pad_dummy << 0 |
vpp_post->vpp_post_pad.vpp_post_pad_rpt_lcol << 30 |
vpp_post->vpp_post_pad.vpp_post_pad_en << 31);
osd_logd2("%s: vpp_post_pad_hsize=%x\n",
__func__, vpp_post->vpp_post_pad.vpp_post_pad_hsize);
} else {
VSYNCOSD_WR_MPEG_REG(VPP_POST_PAD_CTRL, 0);
}
}
#endif
#ifdef AML_T7_DISPLAY
static void viu2_osd1_update_disp_geometry(void)
{
osd_update_disp_geometry(VIU2_OSD1);
}
static void viu3_osd1_update_disp_geometry(void)
{
osd_update_disp_geometry(VIU3_OSD1);
}
#else
static void viu2_osd1_update_disp_geometry(void)
{
u32 data32;
data32 = (osd_hw.dispdata[VIU2_OSD1].x_start & 0xfff)
| (osd_hw.dispdata[VIU2_OSD1].x_end & 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[2].osd_blk0_cfg_w3, data32);
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE)
data32 = ((osd_hw.dispdata[VIU2_OSD1].y_start >> 1) & 0xfff)
| ((((osd_hw.dispdata[VIU2_OSD1].y_end + 1) >> 1) - 1)
& 0xfff) << 16;
else
data32 = (osd_hw.dispdata[VIU2_OSD1].y_start & 0xfff)
| (osd_hw.dispdata[VIU2_OSD1].y_end & 0xfff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[2].osd_blk0_cfg_w4, data32);
data32 = (osd_hw.pandata[VIU2_OSD1].x_start & 0x1fff)
| (osd_hw.pandata[VIU2_OSD1].x_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[2].osd_blk0_cfg_w1, data32);
data32 = (osd_hw.pandata[VIU2_OSD1].y_start & 0x1fff)
| (osd_hw.pandata[VIU2_OSD1].y_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[2].osd_blk0_cfg_w2, data32);
remove_from_update_list(VIU2_OSD1, DISP_GEOMETRY);
}
static void viu3_osd1_update_disp_geometry(void)
{
remove_from_update_list(VIU3_OSD1, DISP_GEOMETRY);
}
#endif
static void osd_update_disp_3d_mode(u32 index)
{
/*step 1 . set pan data */
u32 data32;
if (osd_hw.mode_3d[index].left_right == OSD_LEFT) {
data32 = (osd_hw.mode_3d[index].l_start & 0x1fff)
| (osd_hw.mode_3d[index].l_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
} else {
data32 = (osd_hw.mode_3d[index].r_start & 0x1fff)
| (osd_hw.mode_3d[index].r_end & 0x1fff) << 16;
VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
}
osd_hw.mode_3d[index].left_right ^= 1;
}
static void osd1_update_disp_3d_mode(void)
{
osd_update_disp_3d_mode(OSD1);
}
static void osd2_update_disp_3d_mode(void)
{
osd_update_disp_3d_mode(OSD2);
}
static void osd3_update_disp_3d_mode(void)
{
osd_update_disp_3d_mode(OSD3);
}
static void viu2_osd1_update_disp_3d_mode(void)
{
osd_update_disp_3d_mode(VIU2_OSD1);
}
void osd_hist_enable(u32 osd_index)
{
#ifndef AML_C3_DISPLAY
if (osd_hw.osd_ver == OSD_HIGH_ONE) {
#ifndef AML_S5_DISPLAY
VSYNCOSD_WR_MPEG_REG(VI_HIST_CTRL, 0x1801);
#else
VSYNCOSD_WR_MPEG_REG(VI_HIST_CTRL, 0x3001);
#endif
} else {
if (OSD1 == osd_index) {
VSYNCOSD_WR_MPEG_REG(VI_HIST_CTRL, 0x1801);
} else if (OSD2 == osd_index) {
VSYNCOSD_WR_MPEG_REG(VI_HIST_CTRL, 0x2001);
} else {
osd_loge("osd%d is not supported.\n", osd_index);
}
}
osd_logd("VI_HIST_CTRL = %x\n", VSYNCOSD_RD_MPEG_REG(VI_HIST_CTRL));
#endif
}
int osd_get_hist_stat(u32 *hist_result)
{
#ifndef AML_C3_DISPLAY
hist_result[0] = VSYNCOSD_RD_MPEG_REG(VI_HIST_MAX_MIN);
hist_result[1] = VSYNCOSD_RD_MPEG_REG(VI_HIST_SPL_VAL);
hist_result[2] = VSYNCOSD_RD_MPEG_REG(VI_HIST_SPL_PIX_CNT);
hist_result[3] = VSYNCOSD_RD_MPEG_REG(VI_HIST_CHROMA_SUM);
osd_logd("osd hist stat result:0x%x, 0x%x, 0x%x, 0x%x\n",
hist_result[0], hist_result[1],
hist_result[2], hist_result[3]);
#endif
return 0;
}
#ifdef VEHICLE_CONFIG
/* UBOOT_INFO_FLAG bit definition
* | 31 | 30 | 29 ~ 16 | 15 | 14 | 13 ~ 0 |
* | uboot config finish | screen interlace | screen H | reserved | reserved | screen W |
*
* bit31: 0 - uboot config is finished
* 1 - uboot config is not finished
*/
void transfer_info_to_rtos(void)
{
struct vinfo_s *info = NULL;
int screen_w, screen_h, interlace;
u32 val;
#if defined CONFIG_AML_VOUT
info = vout_get_current_vinfo();
#endif
screen_w = info->width;
screen_h = info->height;
interlace = info->field_height == screen_h ? 0 : 1;
val = (0 << 31) | (interlace << 30) | (screen_h << 16) | screen_w;
VSYNCOSD_WR_MPEG_REG(UBOOT_INFO_FLAG, val);
}
bool is_osd2_configed(void)
{
bool ret = false;
if (VSYNCOSD_RD_MPEG_REG(hw_osd_reg_array[1].osd_ctrl_stat) & 0x1)
ret = true;
printf("%s ret=%d\n", __func__, ret);
return ret;
}
static void osd_set_dimm(u32 index, u32 dim_color)
{
u32 dimm_rgb = 0;
dimm_rgb =
((dim_color & 0xff000000)
>> 24) << 22;
dimm_rgb |=
((dim_color & 0xff0000)
>> 16) << 12;
dimm_rgb |=
((dim_color & 0xff00)
>> 8) << 2;
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_DIMM_CTRL,
0x40000000 | dimm_rgb);
VSYNCOSD_WR_MPEG_REG_BITS
(hw_osd_reg_array[index].osd_ctrl_stat2, 0x1, 14, 1);
VSYNCOSD_WR_MPEG_REG_BITS
(hw_osd_reg_array[index].osd_ctrl_stat2,
dim_color & 0xff, 6, 8);
}
static void osd2_config_blend(void)
{
u32 data;
u32 din_reoder_sel = 0, blend_din_en = 0;
data = osd_reg_read(VIU_OSD_BLEND_CTRL);
din_reoder_sel = data & 0xffff;
blend_din_en = data & 0xf00000;
din_reoder_sel &= ~0xf000;
#ifdef AML_S5_DISPLAY
din_reoder_sel |= 3 << 12;
#else
din_reoder_sel |= 2 << 12;
#endif
blend_din_en &= ~0x400000;
blend_din_en |= 1 << 23;
data &= ~0xf0ffff;
data |= din_reoder_sel | blend_din_en;
osd_reg_write(VIU_OSD_BLEND_CTRL, data);
osd_reg_write(VIU_OSD_BLEND_DIN1_SCOPE_H,
osd_hw.free_dst_data[OSD1].x_end << 16 |
osd_hw.free_dst_data[OSD1].x_start);
osd_reg_write(VIU_OSD_BLEND_DIN1_SCOPE_V,
(osd_hw.free_dst_data[OSD1].y_end) << 16 |
(osd_hw.free_dst_data[OSD1].y_start));
}
void osd2_config_with_dimm(int *axis)
{
osd2_layer_init();
osd_set_free_scale_mode_hw(OSD2, 1);
osd_set_free_scale_axis_hw(OSD2, 0, 0, fb_gdev.fb_width - 1,
fb_gdev.fb_height - 1);
osd_set_window_axis_hw(OSD2, axis[0], axis[1], axis[0] + axis[2] - 1,
axis[1] + axis[3] - 1);
osd_set_free_scale_enable_hw(OSD2, 0x10001);
osd_enable_hw(OSD2, 1);
osd_set_dimm(OSD2, 0x0000);
osd2_config_blend();
}
#endif
#ifdef AML_T7_DISPLAY
void osd_init_hw_viux(u32 index)
{
u32 group, idx, reverse_val = 0;
char *osd_reverse;
char *s;
/* 1:vd1 2:osd1 else :close */
u32 bld_src2_sel = 2;
u32 osd_premult = 0;
u32 blend_en = 1;
u32 data32;
u32 holdline = 8;
/* init osd fifo control register
* set DDR request priority to be urgent
*/
if (index > VIU3_OSD1 || index < VIU2_OSD1)
return;
data32 = 1;
/* hold_fifo_lines */
if (index == VIU2_OSD1)
s = env_get("viu2_hold_line");
else if (index == VIU3_OSD1)
s = env_get("viu3_hold_line");
if (s) {
holdline = simple_strtoul(s, NULL, 10);
data32 |= holdline << 5; /* hold_fifo_lines */
} else {
if (osd_hw.osd_ver == OSD_HIGH_ONE)
data32 |= 8 << 5; /* hold_fifo_lines */
else
data32 |= 4 << 5;
}
/* burst_len_sel: 3=64 */
if (osd_hw.osd_ver == OSD_HIGH_ONE) {
data32 |= 1 << 10;
data32 |= 1 << 31;
} else {
data32 |= 3 << 10;
}
/*
* bit 23:22, fifo_ctrl
* 00 : for 1 word in 1 burst
* 01 : for 2 words in 1 burst
* 10 : for 4 words in 1 burst
* 11 : reserved
*/
data32 |= 2 << 22;
/* bit 28:24, fifo_lim */
data32 |= 2 << 24;
/* fifo_depth_val: 32*8=256 */
data32 |= 64 << 12;
osd_reg_write(hw_osd_reg_array[index].osd_fifo_ctrl_stat, data32);
/* just disable osd to avoid booting hang up */
data32 = 0x0 << 0;
data32 |= OSD_GLOBAL_ALPHA_DEF << 12;
osd_reg_write(hw_osd_reg_array[index].osd_ctrl_stat, data32);
/* set replaced_alpha */
data32 = 0x1 << 14;
data32 |= 0xff << 6;
osd_reg_write(hw_osd_reg_array[index].osd_ctrl_stat2, data32);
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5M)
osd_hw.path_ctrl_independ = 1;
if (index == VIU2_OSD1) {
/* OSD3 -> VPP1 */
if (osd_hw.path_ctrl_independ) {
independ_path_default_regs();
/* osd byp osd_blend */
osd_reg_set_bits(VIU_OSD3_PATH_CTRL, 0x1, 4, 1);
} else {
fix_vpu_clk2_default_regs();
/* osd byp osd_blend */
osd_reg_set_bits(VPP_OSD3_SCALE_CTRL, 0x7, 0, 3);
}
/* vpp1 osd order, premult, blend_en */
osd_reg_set_bits(VPP1_BLD_CTRL, bld_src2_sel, 4, 4);
osd_reg_set_bits(VPP1_BLD_CTRL, osd_premult, 17, 1);
osd_reg_set_bits(VPP1_BLD_CTRL, blend_en, 31, 1);
/* vpp_top input mux */
osd_reg_set_bits(OSD_PATH_MISC_CTRL, OSD3 + VPP_OSD1,
OSD3 * 4 + 16, 4);
/* to vpp_top1 */
osd_reg_set_bits(PATH_START_SEL, VPU_VPP1, 24, 2);
}
if (index == VIU3_OSD1) {
/* OSD4 -> VPP2 */
if (osd_hw.path_ctrl_independ) {
independ_path_default_regs();
/* osd byp osd_blend */
osd_reg_set_bits(VIU_OSD4_PATH_CTRL, 0x1, 4, 1);
} else {
fix_vpu_clk2_default_regs();
/* osd byp osd_blend */
osd_reg_set_bits(VPP_OSD4_SCALE_CTRL, 0x7, 0, 3);
}
/* vpp1 osd order, premult, blend_en */
osd_reg_set_bits(VPP2_BLD_CTRL, bld_src2_sel, 4, 4);
osd_reg_set_bits(VPP2_BLD_CTRL, osd_premult, 17, 1);
osd_reg_set_bits(VPP2_BLD_CTRL, blend_en, 31, 1);
/* vpp_top input mux */
osd_reg_set_bits(OSD_PATH_MISC_CTRL, OSD4 + VPP_OSD1,
OSD4 * 4 + 16, 4);
/* to vpp_top2 */
osd_reg_set_bits(PATH_START_SEL, VPU_VPP2, 28, 2);
}
/* init param */
osd_reverse = env_get("osd_reverse");
for (group = 0; group < HW_OSD_COUNT; group++)
for (idx = 0; idx < HW_REG_INDEX_MAX; idx++)
osd_hw.reg[group][idx].update_func =
hw_func_array[group][idx];
osd_hw.updated[index] = 0;
osd_hw.enable[index] = DISABLE;
osd_hw.fb_gem[index].canvas_idx = OSD4_CANVAS_INDEX;
osd_hw.gbl_alpha[index] = OSD_GLOBAL_ALPHA_DEF;
osd_hw.color_info[index] = NULL;
osd_hw.color_key[index] = 0xffffffff;
osd_hw.scale[index].h_enable = 0;
osd_hw.scale[index].v_enable = 0;
osd_hw.mode_3d[index].enable = 0;
if (osd_reverse) {
if (!strcmp(osd_reverse, "all,true"))
reverse_val = REVERSE_XY;
else if (!strcmp(osd_reverse, "all,x_rev"))
reverse_val = REVERSE_X;
else if (!strcmp(osd_reverse, "all,y_rev"))
reverse_val = REVERSE_Y;
else
reverse_val = REVERSE_NONE;
}
osd_hw.osd_reverse[index] = reverse_val;
osd_hw.rotation_pandata[index].x_start = 0;
osd_hw.rotation_pandata[index].y_start = 0;
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_T7 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_S5 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5M ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3X)
osd_hw.mif_linear = 1;
}
#else
void osd_init_hw_viux(u32 index)
{
u32 group, idx, data32, holdline = 4, reverse_val = 0;
char *osd_reverse;
char *s;
if (index != VIU2_OSD1)
return;
osd_reverse = env_get("osd_reverse");
s = env_get("viu2_hold_line");
if (s)
holdline = simple_strtoul(s, NULL, 10);
for (group = 0; group < HW_OSD_COUNT; group++)
for (idx = 0; idx < HW_REG_INDEX_MAX; idx++)
osd_hw.reg[group][idx].update_func =
hw_func_array[group][idx];
osd_hw.updated[index] = 0;
#ifndef AML_C3_DISPLAY
osd_vpu_power_on_viu2();
osd_reg_write(VPP2_OFIFO_SIZE, 0x7ff00800);
#endif
/* init osd fifo control register */
/* set DDR request priority to be urgent */
data32 = 1;
/* hold_fifo_lines */
data32 |= holdline << 5; /* hold_fifo_lines */
/* burst_len_sel: 3=64 */
data32 |= 1 << 10;
data32 |= 1 << 31;
/*
* bit 23:22, fifo_ctrl
* 00 : for 1 word in 1 burst
* 01 : for 2 words in 1 burst
* 10 : for 4 words in 1 burst
* 11 : reserved
*/
data32 |= 2 << 22;
/* bit 28:24, fifo_lim */
data32 |= 2 << 24;
/* fifo_depth_val: 32 or 64 *8 = 256 or 512 */
data32 |= 64 << 12;
osd_reg_write(hw_osd_reg_array[index].osd_fifo_ctrl_stat, data32);
/* disable osd */
data32 = 0x0 << 0;
data32 |= OSD_GLOBAL_ALPHA_DEF << 12;
data32 |= 0x80000000;
osd_reg_write(hw_osd_reg_array[index].osd_ctrl_stat, data32);
/* set replaced_alpha */
data32 = 0x1 << 14;
data32 |= 0xff << 6;
osd_reg_write(hw_osd_reg_array[index].osd_ctrl_stat2, data32);
osd_hw.enable[index] = DISABLE;
osd_hw.fb_gem[index].canvas_idx = OSD4_CANVAS_INDEX;
osd_hw.gbl_alpha[index] = OSD_GLOBAL_ALPHA_DEF;
osd_hw.color_info[index] = NULL;
osd_hw.color_key[index] = 0xffffffff;
osd_hw.scale[index].h_enable = 0;
osd_hw.scale[index].v_enable = 0;
osd_hw.mode_3d[index].enable = 0;
if (osd_reverse) {
if (!strcmp(osd_reverse, "all,true"))
reverse_val = REVERSE_XY;
else if (!strcmp(osd_reverse, "all,x_rev"))
reverse_val = REVERSE_X;
else if (!strcmp(osd_reverse, "all,y_rev"))
reverse_val = REVERSE_Y;
else
reverse_val = REVERSE_NONE;
}
osd_hw.osd_reverse[index] = reverse_val;
osd_hw.rotation_pandata[index].x_start = 0;
osd_hw.rotation_pandata[index].y_start = 0;
}
#endif
#ifndef AML_C3_DISPLAY
static void set_vpp_super_position(void)
{
#define PREBLD_SR0_VD1_SCALER (1 << 1)
#define DNLP_SR1_CM (1 << 3)
#ifndef AML_S5_DISPLAY
if ((osd_get_chip_type() == MESON_CPU_MAJOR_ID_G12A) ||
(osd_get_chip_type() == MESON_CPU_MAJOR_ID_G12B) ||
(osd_get_chip_type() == MESON_CPU_MAJOR_ID_SM1))
osd_reg_set_mask(VPP_MISC, PREBLD_SR0_VD1_SCALER);
else if ((osd_get_chip_type() == MESON_CPU_MAJOR_ID_TL1) ||
(osd_get_chip_type() >= MESON_CPU_MAJOR_ID_TM2))
osd_reg_set_mask(VPP_MISC, DNLP_SR1_CM);
#endif
}
#endif
static void fix_vpu_clk2_default_regs(void)
{
static int init_done;
if (init_done) {
osd_logd("%s, has been initialized, skip.\n", __func__);
return;
}
init_done = 1;
#if defined(AML_S5_DISPLAY)
/* default: osd byp dolby */
#ifdef CONFIG_AML_DOLBY
if (dolby_vision_on)
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x0, 0, 1);
else
#endif
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x1, 0, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x1, 2, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x1, 4, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x1, 6, 1);
/* default: osd 12bit path */
osd_reg_set_bits(VIU_OSD1_MISC, 1, 17, 1);
osd_reg_set_bits(VIU_OSD2_MISC, 1, 17, 1);
osd_reg_set_bits(VIU_OSD3_MISC, 1, 17, 1);
osd_reg_set_bits(VIU_OSD4_MISC, 1, 17, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x0, 1, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x0, 3, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x0, 5, 1);
osd_reg_set_bits(OSD_DOLBY_BYPASS_EN, 0x0, 7, 1);
/* 2mux1, 0:use mali/mif 1:video */
osd_reg_set_bits(VPP_INTF_OSD3_CTRL, 0, 1, 1);
/* 1mux3, OSD1/3 -> osd_blend */
osd_reg_write(OSD_PROC_1MUX3_SEL, 2 << 0 | 2 << 4);
/* disable PI */
osd_reg_set_bits(OSD_PI_BYPASS_EN, 1, 0, 1);
/* select din1 */
osd_reg_set_bits(OSD_SYS_5MUX4_SEL, 1, 0, 20);
#elif defined(AML_T7_DISPLAY)
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_T7) {
/* default: osd byp osd_blend */
osd_reg_set_bits(VPP_OSD1_SCALE_CTRL, 0x2, 0, 3);
osd_reg_set_bits(VPP_OSD2_SCALE_CTRL, 0x3, 0, 3);
osd_reg_set_bits(VPP_OSD3_SCALE_CTRL, 0x3, 0, 3);
osd_reg_set_bits(VPP_OSD4_SCALE_CTRL, 0x3, 0, 3);
/* default: osd byp dolby */
osd_reg_set_bits(VPP_VD1_DSC_CTRL, 0x1, 4, 1);
osd_reg_set_bits(VPP_VD2_DSC_CTRL, 0x1, 4, 1);
osd_reg_set_bits(VPP_VD3_DSC_CTRL, 0x1, 4, 1);
#ifdef CONFIG_AML_DOLBY
if (dolby_vision_on)
osd_reg_set_bits(MALI_AFBCD_TOP_CTRL, 0x0, 14, 1);
else
#endif
osd_reg_set_bits(MALI_AFBCD_TOP_CTRL, 0x1, 14, 1);
osd_reg_set_bits(MALI_AFBCD_TOP_CTRL, 0x1, 19, 1);
osd_reg_set_bits(MALI_AFBCD1_TOP_CTRL, 0x1, 19, 1);
osd_reg_set_bits(MALI_AFBCD1_TOP_CTRL, 0x1, 19, 1);
/* default: osd 12bit path */
osd_reg_set_bits(VPP_VD1_DSC_CTRL, 0x0, 5, 1);
osd_reg_set_bits(VPP_VD2_DSC_CTRL, 0x0, 5, 1);
osd_reg_set_bits(VPP_VD3_DSC_CTRL, 0x0, 5, 1);
osd_reg_set_bits(MALI_AFBCD_TOP_CTRL, 0x0, 15, 1);
osd_reg_set_bits(MALI_AFBCD_TOP_CTRL, 0x0, 20, 1);
osd_reg_set_bits(MALI_AFBCD1_TOP_CTRL, 0x0, 20, 1);
osd_reg_set_bits(MALI_AFBCD1_TOP_CTRL, 0x0, 20, 1);
/* clean vpp_top 1/2 blend default order */
osd_reg_set_bits(VPP1_BLD_CTRL, 0x0, 0, 8);
osd_reg_set_bits(VPP2_BLD_CTRL, 0x0, 0, 8);
/* set vpp_top 1/2 default blend dummy */
osd_reg_write(VPP1_BLEND_BLEND_DUMMY_DATA, 0x008080);
osd_reg_write(VPP1_BLEND_DUMMY_ALPHA, 0xffffffff);
osd_reg_write(VPP2_BLEND_BLEND_DUMMY_DATA, 0x008080);
osd_reg_write(VPP2_BLEND_DUMMY_ALPHA, 0xffffffff);
}
#endif
}
static void independ_path_default_regs(void)
{
#ifndef AML_C3_DISPLAY
static int init_done;
if (init_done) {
osd_logd("%s, has been initialized, skip.\n", __func__);
return;
}
init_done = 1;
/* default: osd1_bld_din_sel -- do not osd_data_byp osd_blend */
osd_reg_set_bits(VIU_OSD1_PATH_CTRL, 0x0, 4, 1);
osd_reg_set_bits(VIU_OSD2_PATH_CTRL, 0x0, 4, 1);
osd_reg_set_bits(VIU_OSD3_PATH_CTRL, 0x0, 4, 1);
/* default: osd1_sc_path_sel -- before osd_blend or after hdr */
osd_reg_set_bits(VIU_OSD1_PATH_CTRL, 0x0, 0, 1);
osd_reg_set_bits(VIU_OSD2_PATH_CTRL, 0x1, 0, 1);
osd_reg_set_bits(VIU_OSD3_PATH_CTRL, 0x1, 0, 1);
/* default: osd byp dolby */
osd_reg_set_bits(VIU_VD1_PATH_CTRL, 0x1, 16, 1);
osd_reg_set_bits(VIU_VD2_PATH_CTRL, 0x1, 16, 1);
osd_reg_set_bits(VIU_OSD1_PATH_CTRL, 0x1, 16, 1);
osd_reg_set_bits(VIU_OSD2_PATH_CTRL, 0x1, 16, 1);
osd_reg_set_bits(VIU_OSD3_PATH_CTRL, 0x1, 16, 1);
/* default: osd 12bit path */
osd_reg_set_bits(VIU_VD1_PATH_CTRL, 0x0, 17, 1);
osd_reg_set_bits(VIU_VD2_PATH_CTRL, 0x0, 17, 1);
osd_reg_set_bits(VIU_OSD1_PATH_CTRL, 0x0, 17, 1);
osd_reg_set_bits(VIU_OSD2_PATH_CTRL, 0x0, 17, 1);
osd_reg_set_bits(VIU_OSD3_PATH_CTRL, 0x0, 17, 1);
/* clean vpp_top 1/2 blend default order */
osd_reg_set_bits(VPP1_BLD_CTRL, 0x0, 0, 8);
osd_reg_set_bits(VPP2_BLD_CTRL, 0x0, 0, 8);
/* set vpp_top 1/2 default blend dummy */
osd_reg_write(VPP1_BLEND_BLEND_DUMMY_DATA, 0x008080);
osd_reg_write(VPP1_BLEND_DUMMY_ALPHA, 0xffffffff);
osd_reg_write(VPP2_BLEND_BLEND_DUMMY_DATA, 0x008080);
osd_reg_write(VPP2_BLEND_DUMMY_ALPHA, 0xffffffff);
#endif
}
static void switch_osd_to_dmcx(u32 dmc_num)
{
#ifndef AML_C3_DISPLAY
static int init;
u32 val = 0;
if (init)
return;
init = 1;
osd_logd("%s, dmc%d\n", __func__, dmc_num);
if (dmc_num == 1) {
/* OSD1->vpp_arb1 */
val |= 1 << 20;
/* OSD2->vpp_arb1 */
val |= 1 << 21;
/* OSD3->vpp_arb1 */
val |= 1 << 24;
/* OSD4->vpp_arb1 */
val |= 1 << 25;
/* mali afbcd->vpp_arb1 */
val |= 1 << 27;
osd_reg_write(VPP_RDARB_MODE, val);
/* vpp_arb1->vpu arb read2 */
osd_reg_set_bits(VPU_RDARB_MODE_L2C1, 0, 16, 1);
osd_reg_set_bits(VPU_RDARB_MODE_L2C1, 1, 17, 1);
} else {
osd_reg_write(VPP_RDARB_MODE, 0);
osd_reg_set_bits(VPU_RDARB_MODE_L2C1, 0, 16, 1);
}
#endif
}
void osd_init_hw(void)
{
u32 group, idx, data32, data2, holdline = 8, reverse_val = 0;
char *osd_reverse;
char *s;
/* T5M RevA, switch osd to dmc1
* T5M RevB, switch osd to dmc0
*/
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5M) {
if (get_cpu_id().chip_rev == MESON_CPU_CHIP_REVISION_A)
switch_osd_to_dmcx(1);
else
switch_osd_to_dmcx(0);
}
osd_reverse = env_get("osd_reverse");
for (group = 0; group < HW_OSD_COUNT; group++)
for (idx = 0; idx < HW_REG_INDEX_MAX; idx++)
osd_hw.reg[group][idx].update_func =
hw_func_array[group][idx];
osd_hw.updated[OSD1] = 0;
osd_hw.updated[OSD2] = 0;
osd_hw.updated[OSD3] = 0;
osd_hw.updated[OSD4] = 0;
/* set display output resolution */
#if defined CONFIG_AML_VOUT
struct vinfo_s *info = NULL;
info = vout_get_current_vinfo();
if (info != NULL)
osd_reg_write(VPP_POSTBLEND_H_SIZE, info->width);
#endif
osd_vpu_power_on();
#ifdef AML_C3_DISPLAY
irq_clr_c3();
#endif
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5W ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5M)
osd_hw.path_ctrl_independ = 1;
#ifdef AML_S5_DISPLAY
osd_hw.has_pi = 1;
#endif
/* here we will init default value ,these value only set once . */
if (!logo_loaded) {
if (osd_hw.path_ctrl_independ)
independ_path_default_regs();
else
fix_vpu_clk2_default_regs();
#ifndef AML_C3_DISPLAY
/* init vpu fifo control register */
data32 = osd_reg_read(VPP_OFIFO_SIZE);
osd_logi("VPP_OFIFO_SIZE:0x%x\n", data32);
if (osd_hw.osd_ver == OSD_HIGH_ONE) {
data32 &= ~((0xfff << 20) | 0x3fff);
data32 |= (0xfff << 20);
data32 |= (0xfff + 1);
osd_reg_write(VPP_OFIFO_SIZE, data32);
}
#endif
/* init osd fifo control register */
/* set DDR request priority to be urgent */
data32 = 1;
if ((osd_get_chip_type() == MESON_CPU_MAJOR_ID_M6TV)
|| (osd_get_chip_type() == MESON_CPU_MAJOR_ID_MTVD)) {
data32 |= 18 << 5; /* hold_fifo_lines */
} else if (osd_hw.osd_ver == OSD_SIMPLE &&
osd_get_chip_type() != MESON_CPU_MAJOR_ID_A4) {
data32 &= ~(0x1f << 5); /* bit[9:5] HOLD_FIFO_LINES */
data32 |= 0x18 << 5;
} else {
s = env_get("viu1_hold_line");
if (s) {
holdline = simple_strtoul(s, NULL, 10);
data32 |= holdline << 5; /* hold_fifo_lines */
} else {
if (osd_hw.osd_ver == OSD_HIGH_ONE)
data32 |= 8 << 5; /* hold_fifo_lines */
else
data32 |= 4 << 5; /* hold_fifo_lines */
}
}
/* burst_len_sel: 3=64 */
if (osd_hw.osd_ver == OSD_HIGH_ONE ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_A4) {
data32 |= 1 << 10;
data32 |= 1 << 31;
} else
data32 |= 3 << 10;
if (osd_get_chip_type() >= MESON_CPU_MAJOR_ID_GXBB) {
/*
* bit 23:22, fifo_ctrl
* 00 : for 1 word in 1 burst
* 01 : for 2 words in 1 burst
* 10 : for 4 words in 1 burst
* 11 : reserved
*/
data32 |= 2 << 22;
/* bit 28:24, fifo_lim */
data32 |= 2 << 24;
}
data2 = data32;
/* fifo_depth_val: 32*8=256 */
if ((osd_get_chip_type() == MESON_CPU_MAJOR_ID_TXL)
|| (osd_get_chip_type() == MESON_CPU_MAJOR_ID_TXLX))
data32 |= 64 << 12;
else
data32 |= 32 << 12;
data2 |= 32 << 12;
osd_reg_write(hw_osd_reg_array[0].osd_fifo_ctrl_stat, data32);
osd_reg_write(hw_osd_reg_array[1].osd_fifo_ctrl_stat, data2);
#ifndef AML_C3_DISPLAY
osd_reg_set_mask(VPP_MISC, VPP_POSTBLEND_EN);
osd_reg_clr_mask(VPP_MISC, VPP_PREBLEND_EN);
if (osd_hw.osd_ver <= OSD_NORMAL)
osd_reg_clr_mask(VPP_MISC,
VPP_OSD1_POSTBLEND |
VPP_OSD2_POSTBLEND | VPP_VD1_POSTBLEND);
#endif
/* just disable osd to avoid booting hang up */
data32 = 0x0 << 0;
if (osd_get_chip_type() != MESON_CPU_MAJOR_ID_A4)
data32 |= OSD_GLOBAL_ALPHA_DEF << 12;
else
data32 |= 0x100 << 12;
osd_reg_write(hw_osd_reg_array[0].osd_ctrl_stat, data32);
osd_reg_write(hw_osd_reg_array[1].osd_ctrl_stat, data32);
/* set replaced_alpha */
data32 = 0x1 << 14;
data32 |= 0xff << 6;
osd_reg_write(hw_osd_reg_array[0].osd_ctrl_stat2, data32);
osd_reg_write(hw_osd_reg_array[1].osd_ctrl_stat2, data32);
logo_loaded = 1;
}
#ifndef AML_C3_DISPLAY
if (osd_hw.osd_ver <= OSD_NORMAL)
osd_reg_clr_mask(VPP_MISC, VPP_POST_FG_OSD2 | VPP_PRE_FG_OSD2);
else if (osd_hw.osd_ver > OSD_NORMAL)
set_vpp_super_position();
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_S4)
osd_reg_clr_mask(VPP_MISC, VPP_WATER_MARK_10BIT);
#else
osd1_matrix_yuv2rgb(0);
#endif
osd_hw.order = OSD_ORDER_01;
osd_hw.enable[OSD1] = DISABLE;
osd_hw.enable[OSD2] = DISABLE;
osd_hw.enable[OSD3] = DISABLE;
osd_hw.enable[OSD4] = DISABLE;
osd_hw.fb_gem[OSD1].canvas_idx = OSD1_CANVAS_INDEX;
osd_hw.fb_gem[OSD2].canvas_idx = OSD2_CANVAS_INDEX;
osd_hw.fb_gem[OSD3].canvas_idx = OSD3_CANVAS_INDEX;
osd_hw.fb_gem[OSD4].canvas_idx = OSD4_CANVAS_INDEX;
osd_hw.gbl_alpha[OSD1] = OSD_GLOBAL_ALPHA_DEF;
osd_hw.gbl_alpha[OSD2] = OSD_GLOBAL_ALPHA_DEF;
osd_hw.gbl_alpha[OSD3] = OSD_GLOBAL_ALPHA_DEF;
osd_hw.gbl_alpha[OSD4] = OSD_GLOBAL_ALPHA_DEF;
osd_hw.color_info[OSD1] = NULL;
osd_hw.color_info[OSD2] = NULL;
osd_hw.color_info[OSD3] = NULL;
osd_hw.color_info[OSD4] = NULL;
osd_hw.color_key[OSD1] = 0xffffffff;
osd_hw.color_key[OSD2] = 0xffffffff;
osd_hw.color_key[OSD3] = 0xffffffff;
osd_hw.color_key[OSD4] = 0xffffffff;
osd_hw.free_scale_enable[OSD1] = 0;
osd_hw.free_scale_enable[OSD2] = 0;
osd_hw.free_scale_enable[OSD3] = 0;
osd_hw.free_scale_enable[OSD4] = 0;
osd_hw.scale[OSD1].h_enable = 0;
osd_hw.scale[OSD1].v_enable = 0;
osd_hw.scale[OSD2].h_enable = 0;
osd_hw.scale[OSD2].v_enable = 0;
osd_hw.scale[OSD3].h_enable = 0;
osd_hw.scale[OSD3].v_enable = 0;
osd_hw.scale[OSD4].h_enable = 0;
osd_hw.scale[OSD4].v_enable = 0;
osd_hw.mode_3d[OSD1].enable = 0;
osd_hw.mode_3d[OSD2].enable = 0;
osd_hw.mode_3d[OSD3].enable = 0;
osd_hw.mode_3d[OSD4].enable = 0;
osd_hw.block_mode[OSD1] = 0;
osd_hw.block_mode[OSD2] = 0;
osd_hw.block_mode[OSD3] = 0;
osd_hw.block_mode[OSD4] = 0;
osd_hw.free_scale[OSD1].h_enable = 0;
osd_hw.free_scale[OSD1].v_enable = 0;
osd_hw.free_scale[OSD2].h_enable = 0;
osd_hw.free_scale[OSD2].v_enable = 0;
osd_hw.free_scale[OSD3].h_enable = 0;
osd_hw.free_scale[OSD3].v_enable = 0;
osd_hw.free_scale[OSD4].h_enable = 0;
osd_hw.free_scale[OSD4].v_enable = 0;
if (osd_reverse) {
if (!strcmp(osd_reverse, "all,true"))
reverse_val = REVERSE_XY;
else if (!strcmp(osd_reverse, "all,x_rev"))
reverse_val = REVERSE_X;
else if (!strcmp(osd_reverse, "all,y_rev"))
reverse_val = REVERSE_Y;
else
reverse_val = REVERSE_NONE;
}
osd_hw.osd_reverse[OSD1] = reverse_val;
osd_hw.osd_reverse[OSD2] = reverse_val;
osd_hw.osd_reverse[OSD3] = reverse_val;
osd_hw.osd_reverse[OSD4] = reverse_val;
osd_hw.rotation_pandata[OSD1].x_start = 0;
osd_hw.rotation_pandata[OSD1].y_start = 0;
osd_hw.rotation_pandata[OSD2].x_start = 0;
osd_hw.rotation_pandata[OSD2].y_start = 0;
osd_hw.rotation_pandata[OSD3].x_start = 0;
osd_hw.rotation_pandata[OSD3].y_start = 0;
osd_hw.rotation_pandata[OSD4].x_start = 0;
osd_hw.rotation_pandata[OSD4].y_start = 0;
osd_hw.antiflicker_mode = 0;
if (osd_get_chip_type() >= MESON_CPU_MAJOR_ID_M8) {
osd_hw.free_scale_data[OSD1].x_start = 0;
osd_hw.free_scale_data[OSD1].x_end = 0;
osd_hw.free_scale_data[OSD1].y_start = 0;
osd_hw.free_scale_data[OSD1].y_end = 0;
osd_hw.free_scale_data[OSD2].x_start = 0;
osd_hw.free_scale_data[OSD2].x_end = 0;
osd_hw.free_scale_data[OSD2].y_start = 0;
osd_hw.free_scale_data[OSD2].y_end = 0;
osd_hw.free_scale_data[OSD3].x_start = 0;
osd_hw.free_scale_data[OSD3].x_end = 0;
osd_hw.free_scale_data[OSD3].y_start = 0;
osd_hw.free_scale_data[OSD3].y_end = 0;
osd_hw.free_scale_data[OSD4].x_start = 0;
osd_hw.free_scale_data[OSD4].x_end = 0;
osd_hw.free_scale_data[OSD4].y_start = 0;
osd_hw.free_scale_data[OSD4].y_end = 0;
osd_hw.free_scale_mode[OSD1] = 1;
osd_hw.free_scale_mode[OSD2] = 1;
osd_hw.free_scale_mode[OSD3] = 1;
osd_hw.free_scale_mode[OSD4] = 1;
if ((osd_get_chip_type() == MESON_CPU_MAJOR_ID_GXM)
||(osd_get_chip_type() == MESON_CPU_MAJOR_ID_TXLX))
osd_reg_write(hw_osd_reg_array[0].osd_sc_dummy_data,
0x00202000);
else if (osd_get_chip_type() ==
MESON_CPU_MAJOR_ID_GXTVBB)
osd_reg_write(hw_osd_reg_array[0].osd_sc_dummy_data, 0xff);
else
osd_reg_write(hw_osd_reg_array[0].osd_sc_dummy_data,
0x00808000);
} else {
osd_hw.free_scale_mode[OSD1] = 0;
osd_hw.free_scale_mode[OSD2] = 0;
osd_hw.free_scale_mode[OSD3] = 0;
osd_hw.free_scale_mode[OSD4] = 0;
}
memset(osd_hw.rotate, 0, sizeof(struct osd_rotate_s) * HW_OSD_COUNT);
if ((osd_get_chip_type() == MESON_CPU_MAJOR_ID_G12A) ||
((osd_get_chip_type() == MESON_CPU_MAJOR_ID_G12B) &&
(get_cpu_id().chip_rev == MESON_CPU_CHIP_REVISION_A)))
osd_hw.shift_line = 1;
else
osd_hw.shift_line = 0;
if (osd_get_chip_type() == MESON_CPU_MAJOR_ID_T7 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_S5 ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5W ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T5M ||
osd_get_chip_type() == MESON_CPU_MAJOR_ID_T3X)
osd_hw.mif_linear = 1;
return;
}