3389 lines
94 KiB
C
3389 lines
94 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
|
/*
|
|
* drivers/display/osd/osd_hw.c
|
|
*
|
|
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
/* System Headers */
|
|
#include <config.h>
|
|
#include <common.h>
|
|
#include <asm/arch/io.h>
|
|
#include <asm/cpu_id.h>
|
|
#include <asm/arch/cpu.h>
|
|
#include <asm/arch/timer.h>
|
|
|
|
/* Local Headers */
|
|
#include <amlogic/vmode.h>
|
|
#ifdef CONFIG_AML_CANVAS
|
|
#include <amlogic/canvas.h>
|
|
#endif
|
|
#ifdef CONFIG_AML_VOUT
|
|
#include <amlogic/vout.h>
|
|
#endif
|
|
#ifdef CONFIG_AML_VPU_REG_NEW
|
|
#include <asm/arch/register.h>
|
|
#endif
|
|
#include <amlogic/fb.h>
|
|
#include <video_fb.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 "vpp.h"
|
|
|
|
static bool vsync_hit;
|
|
static bool osd_vf_need_update;
|
|
|
|
unsigned int osd_log_level = 0;
|
|
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 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
|
|
};
|
|
|
|
#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
|
|
#define MATRIX_5x3_COEF_SIZE 24
|
|
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
|
|
|
|
static void osd_vpu_power_on(void)
|
|
{
|
|
}
|
|
|
|
#ifndef CONFIG_AML_T7_DISPLAY
|
|
#ifdef CONFIG_AML_MESON_G12A
|
|
static void osd_vpu_power_on_viu2(void)
|
|
{
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
static void osd_super_scale_mem_power_on(void)
|
|
{
|
|
}
|
|
|
|
static void osd_super_scale_mem_power_off(void)
|
|
{
|
|
}
|
|
|
|
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_viu2_osd1)
|
|
{
|
|
if (enable_osd1)
|
|
osd1_update_disp_3d_mode();
|
|
if (enable_osd2)
|
|
osd2_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)
|
|
{
|
|
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);
|
|
}
|
|
|
|
static inline void wait_vsync_wakeup(void)
|
|
{
|
|
int i = 0;
|
|
int enc_line = 0;
|
|
int active_line_begin;
|
|
int vsync_line = 0;
|
|
struct vinfo_s *info = NULL;
|
|
int line_after = 0;
|
|
|
|
#ifdef CONFIG_AML_VOUT
|
|
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 >= active_line_begin * 50 / 100 &&
|
|
enc_line < (vsync_line + active_line_begin * 105 / 100)) {
|
|
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
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
static void vsync_isr(void)
|
|
{
|
|
unsigned int odd_even;
|
|
unsigned int scan_line_number = 0;
|
|
unsigned int fb0_cfg_w0, fb1_cfg_w0;
|
|
int enc_line = 0;
|
|
int active_line_begin;
|
|
|
|
osd_check_scan_mode();
|
|
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE) {
|
|
fb0_cfg_w0 = osd_reg_read(VIU_OSD1_BLK0_CFG_W0);
|
|
fb1_cfg_w0 = osd_reg_read(VIU_OSD2_BLK0_CFG_W0);
|
|
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);
|
|
}
|
|
fb0_cfg_w0 &= ~1;
|
|
fb1_cfg_w0 &= ~1;
|
|
fb0_cfg_w0 |= odd_even;
|
|
fb1_cfg_w0 |= odd_even;
|
|
osd_reg_write(VIU_OSD1_BLK0_CFG_W0, fb0_cfg_w0);
|
|
osd_reg_write(VIU_OSD2_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[VIU2_OSD1].enable);
|
|
|
|
get_encp_line(&enc_line, &active_line_begin);
|
|
if (enc_line > 0 && enc_line <= active_line_begin + 1080)
|
|
osd_logd("exit enc_line=%d,active_line_begin=%d\n",
|
|
enc_line,
|
|
active_line_begin);
|
|
}
|
|
|
|
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 == OSD2) {
|
|
if (real_scan_mode == SCAN_MODE_INTERLACE)
|
|
return 1;
|
|
// data32 = (osd_reg_read(VIU_OSD2_BLK0_CFG_W0) & 3) >> 1;
|
|
} else
|
|
data32 = (osd_reg_read(VIU_OSD1_BLK0_CFG_W0) & 3) >> 1;
|
|
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 (get_cpu_id().family_id == 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 CONFIG_AML_MESON_G12A
|
|
/* 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;
|
|
#ifdef CONFIG_AML_VPU_REG_NEW
|
|
u32 reg_offset = 2 << 2;
|
|
#else
|
|
u32 reg_offset = 2;
|
|
#endif
|
|
u32 shift_line = osd_hw.shift_line;
|
|
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5W)
|
|
postbld_src3_sel = 4;
|
|
|
|
if (index == OSD1)
|
|
din_reoder_sel = 0x4441;
|
|
else if (index == OSD2)
|
|
din_reoder_sel = 0x4442;
|
|
/* 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 */
|
|
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);
|
|
/* vpp osd2 blend ctrl */
|
|
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);
|
|
|
|
/* 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);
|
|
}
|
|
|
|
osd_reg_write(VIU_OSD_BLEND_BLEND0_SIZE,
|
|
height << 16 |
|
|
width);
|
|
osd_reg_write(VIU_OSD_BLEND_BLEND1_SIZE,
|
|
height << 16 |
|
|
width);
|
|
osd_reg_write(VPP_OSD1_IN_SIZE,
|
|
height << 16 | width);
|
|
|
|
/* 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;
|
|
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 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 = VIU_OSD1_BLK1_CFG_W4;
|
|
u32 osd_blk2_cfg_w4 = VIU_OSD1_BLK2_CFG_W4;
|
|
u32 osd_ctrl_stat = VIU_OSD1_CTRL_STAT;
|
|
|
|
switch (index) {
|
|
case 0:
|
|
osd_blk1_cfg_w4 = VIU_OSD1_BLK1_CFG_W4;
|
|
osd_blk2_cfg_w4 = VIU_OSD1_BLK2_CFG_W4;
|
|
osd_ctrl_stat = VIU_OSD1_CTRL_STAT;
|
|
break;
|
|
case 1:
|
|
osd_blk1_cfg_w4 = VIU_OSD2_BLK1_CFG_W4;
|
|
osd_blk2_cfg_w4 = VIU_OSD2_BLK2_CFG_W4;
|
|
osd_ctrl_stat = VIU_OSD2_CTRL_STAT;
|
|
break;
|
|
case 2:
|
|
osd_blk1_cfg_w4 = VIU_OSD3_BLK1_CFG_W4;
|
|
osd_blk2_cfg_w4 = VIU_OSD3_BLK2_CFG_W4;
|
|
osd_ctrl_stat = VIU_OSD3_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);
|
|
}
|
|
|
|
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;
|
|
|
|
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(
|
|
VIU_OSD1_BLK1_CFG_W4,
|
|
osd_hw.fb_gem[index].addr);
|
|
VSYNCOSD_WR_MPEG_REG_BITS(
|
|
VIU_OSD1_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);
|
|
} else {
|
|
if (index < VIU2_OSD1) {
|
|
#ifdef CONFIG_AML_CANVAS
|
|
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
|
|
} else {
|
|
/* for dual logo display */
|
|
osd_hw.fb_gem[index].addr +=
|
|
fb_gdev.fb_height *
|
|
CANVAS_ALIGNED(fb_gdev.fb_width * color->bpp >> 3);
|
|
#ifdef CONFIG_AML_CANVAS
|
|
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
|
|
}
|
|
}
|
|
}
|
|
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 CONFIG_AML_MESON_G12A
|
|
if (osd_hw.osd_ver == OSD_HIGH_ONE && index < VIU2_OSD1)
|
|
osd_setting_default_hwc(index, &disp_data);
|
|
#endif
|
|
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(VIU_OSD1_COLOR_ADDR + REG_OFFSET * index,
|
|
regno);
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_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();
|
|
}
|
|
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;
|
|
osd_logi("osd_hw.free_dst_data: %d,%d,%d,%d\n",x0,x1,y0,y1);
|
|
#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
|
|
}
|
|
|
|
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 {
|
|
if (get_cpu_id().family_id == 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 (get_cpu_id().family_id == 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(VIU_OSD1_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(VIU_OSD2_FIFO_CTRL_STAT,
|
|
1 << 0);
|
|
}
|
|
}
|
|
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 osd1_update_disp_scale_enable(void)
|
|
{
|
|
if (osd_hw.scale[OSD1].h_enable)
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU_OSD1_BLK0_CFG_W0, 3 << 12);
|
|
else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD1_BLK0_CFG_W0, 3 << 12);
|
|
if (osd_hw.scan_mode != SCAN_MODE_INTERLACE) {
|
|
if (osd_hw.scale[OSD1].v_enable)
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU_OSD1_BLK0_CFG_W0,
|
|
1 << 14);
|
|
else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD1_BLK0_CFG_W0,
|
|
1 << 14);
|
|
}
|
|
}
|
|
|
|
static void osd2_update_disp_scale_enable(void)
|
|
{
|
|
if (osd_hw.scale[OSD2].h_enable) {
|
|
#if defined(CONFIG_FB_OSD2_CURSOR)
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0, 3 << 12);
|
|
#else
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0, 3 << 12);
|
|
#endif
|
|
} else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0, 3 << 12);
|
|
if (osd_hw.scan_mode != SCAN_MODE_INTERLACE) {
|
|
if (osd_hw.scale[OSD2].v_enable) {
|
|
#if defined(CONFIG_FB_OSD2_CURSOR)
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0,
|
|
1 << 14);
|
|
#else
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0,
|
|
1 << 14);
|
|
#endif
|
|
} else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0,
|
|
1 << 14);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_disp_scale_enable(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_disp_scale_enable(void)
|
|
{
|
|
if (osd_hw.scale[VIU2_OSD1].h_enable)
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU2_OSD1_BLK0_CFG_W0, 3 << 12);
|
|
else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU2_OSD1_BLK0_CFG_W0, 3 << 12);
|
|
if (osd_hw.scan_mode != SCAN_MODE_INTERLACE) {
|
|
if (osd_hw.scale[VIU2_OSD1].v_enable)
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU2_OSD1_BLK0_CFG_W0,
|
|
1 << 14);
|
|
else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU2_OSD1_BLK0_CFG_W0,
|
|
1 << 14);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void osd_super_scale_enable(u32 index)
|
|
{
|
|
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(VPP_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(VPP_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(VPP_OSD_SCO_V_START_END, data32);
|
|
}
|
|
|
|
static void osd_super_scale_disable(void)
|
|
{
|
|
/* disable osd scaler path */
|
|
VSYNCOSD_WR_MPEG_REG(VPP_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();
|
|
}
|
|
|
|
static void osd1_update_disp_freescale_enable(void)
|
|
{
|
|
u64 hf_phase_step, vf_phase_step;
|
|
int src_w, src_h, dst_w, dst_h;
|
|
int bot_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 = 0;
|
|
u32 data32 = 0x0;
|
|
u32 shift_line = osd_hw.shift_line;
|
|
|
|
osd_logi("osd1_update_disp_freescale_enable\n");
|
|
if (osd_hw.scale_workaround)
|
|
vf_bank_len = 2;
|
|
else
|
|
vf_bank_len = 4;
|
|
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;
|
|
}
|
|
hsc_ini_rcv_num = hf_bank_len;
|
|
vsc_ini_rcv_num = vf_bank_len;
|
|
hsc_ini_rpt_p0_num = hf_bank_len / 2 - 1;
|
|
vsc_ini_rpt_p0_num =
|
|
(vf_bank_len / 2 - 1) > 0 ? (vf_bank_len / 2 - 1) : 0;
|
|
src_w = osd_hw.free_scale_width[OSD1];
|
|
src_h = osd_hw.free_scale_height[OSD1];
|
|
dst_w = osd_hw.free_dst_data[OSD1].x_end -
|
|
osd_hw.free_dst_data[OSD1].x_start + 1;
|
|
dst_h = osd_hw.free_dst_data[OSD1].y_end -
|
|
osd_hw.free_dst_data[OSD1].y_start + 1;
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_MG9TV) {
|
|
/* super scaler mode */
|
|
if (osd_hw.free_scale_mode[OSD1] & 0x2) {
|
|
if (osd_hw.free_scale_enable[OSD1])
|
|
osd_super_scale_enable(OSD1);
|
|
else
|
|
osd_super_scale_disable();
|
|
remove_from_update_list(OSD1, DISP_FREESCALE_ENABLE);
|
|
return;
|
|
}
|
|
}
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale_enable[OSD1]) {
|
|
/* enable osd scaler */
|
|
if (osd_hw.free_scale_mode[OSD1] & 0x1) {
|
|
data32 |= 1 << 2; /* enable osd scaler */
|
|
data32 |= 1 << 3; /* enable osd scaler path */
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SC_CTRL0, data32);
|
|
}
|
|
} else {
|
|
/* disable osd scaler path */
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SC_CTRL0, 0);
|
|
}
|
|
|
|
hf_phase_step = ((u64)src_w << 24) / dst_w;
|
|
vf_phase_step = ((u64)src_h << 20) / dst_h;
|
|
|
|
if (osd_hw.field_out_en) /* interlace output */
|
|
bot_ini_phase = ((vf_phase_step / 2) >> 4);
|
|
else
|
|
bot_ini_phase = 0;
|
|
vf_phase_step = (vf_phase_step << 4);
|
|
/* config osd scaler in/out hv size */
|
|
if (shift_line)
|
|
vsc_ini_rcv_num++;
|
|
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale_enable[OSD1]) {
|
|
data32 = (((src_h - 1 + shift_line) & 0x1fff)
|
|
| ((src_w - 1) & 0x1fff) << 16);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCI_WH_M1, data32);
|
|
data32 = ((osd_hw.free_dst_data[OSD1].x_end & 0xfff) |
|
|
(osd_hw.free_dst_data[OSD1].x_start & 0xfff) << 16);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCO_H_START_END, data32);
|
|
data32 = ((osd_hw.free_dst_data[OSD1].y_end & 0xfff) |
|
|
(osd_hw.free_dst_data[OSD1].y_start & 0xfff) << 16);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCO_V_START_END, data32);
|
|
}
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale[OSD1].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;
|
|
}
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_VSC_CTRL0, data32);
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale[OSD1].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(VPP_OSD_HSC_CTRL0, data32);
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale_enable[OSD1]) {
|
|
data32 |= (bot_ini_phase & 0xffff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OSD_HSC_PHASE_STEP,
|
|
hf_phase_step, 0, 28);
|
|
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OSD_HSC_INI_PHASE, 0, 0, 16);
|
|
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OSD_VSC_PHASE_STEP,
|
|
vf_phase_step, 0, 28);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_VSC_INI_PHASE, data32);
|
|
}
|
|
remove_from_update_list(OSD1, DISP_FREESCALE_ENABLE);
|
|
}
|
|
|
|
static void osd1_update_coef(void)
|
|
{
|
|
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(VPP_OSD_SCALE_COEF_IDX, 0x0000, 0, 9);
|
|
for (i = 0; i < 33; i++)
|
|
osd_reg_write(VPP_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(VPP_OSD_SCALE_COEF_IDX, 0x0100, 0, 9);
|
|
for (i = 0; i < 33; i++)
|
|
osd_reg_write(VPP_OSD_SCALE_COEF, hf_coef[i]);
|
|
}
|
|
}
|
|
remove_from_update_list(OSD1, OSD_FREESCALE_COEF);
|
|
}
|
|
|
|
static void osd2_update_disp_freescale_enable(void)
|
|
{
|
|
u64 hf_phase_step, vf_phase_step;
|
|
int src_w, src_h, dst_w, dst_h;
|
|
int bot_ini_phase;
|
|
int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
|
|
int vsc_bot_rcv_num = 6, vsc_bot_rpt_p0_num = 2;
|
|
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;
|
|
|
|
if (osd_hw.scale_workaround)
|
|
vf_bank_len = 2;
|
|
hsc_ini_rcv_num = hf_bank_len;
|
|
vsc_ini_rcv_num = vf_bank_len;
|
|
hsc_ini_rpt_p0_num = hf_bank_len / 2 - 1;
|
|
vsc_ini_rpt_p0_num =
|
|
(vf_bank_len / 2 - 1) > 0 ? (vf_bank_len / 2 - 1) : 0;
|
|
src_w = osd_hw.free_scale_width[OSD2];
|
|
src_h = osd_hw.free_scale_height[OSD2];
|
|
dst_w = osd_hw.free_dst_data[OSD2].x_end -
|
|
osd_hw.free_dst_data[OSD2].x_start + 1;
|
|
dst_h = osd_hw.free_dst_data[OSD2].y_end -
|
|
osd_hw.free_dst_data[OSD2].y_start + 1;
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_MG9TV) {
|
|
/* super scaler mode */
|
|
if (osd_hw.free_scale_mode[OSD2] & 0x2) {
|
|
if (osd_hw.free_scale_enable[OSD2])
|
|
osd_super_scale_enable(OSD2);
|
|
else
|
|
osd_super_scale_disable();
|
|
remove_from_update_list(OSD2, DISP_FREESCALE_ENABLE);
|
|
return;
|
|
}
|
|
}
|
|
/* config osd sc control reg */
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale_enable[OSD2]) {
|
|
/* enable osd scaler */
|
|
if (osd_hw.free_scale_mode[OSD2] & 0x1) {
|
|
data32 |= 1; /* select osd2 input */
|
|
data32 |= 1 << 2; /* enable osd scaler */
|
|
data32 |= 1 << 3; /* enable osd scaler path */
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SC_CTRL0, data32);
|
|
}
|
|
} else {
|
|
/* disable osd scaler path */
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SC_CTRL0, 0);
|
|
}
|
|
|
|
hf_phase_step = ((u64)src_w << 24) / dst_w;
|
|
vf_phase_step = ((u64)src_h << 20) / dst_h;
|
|
|
|
if (osd_hw.field_out_en) /* interlace output */
|
|
bot_ini_phase = ((vf_phase_step / 2) >> 4);
|
|
else
|
|
bot_ini_phase = 0;
|
|
vf_phase_step = (vf_phase_step << 4);
|
|
/* config osd scaler in/out hv size */
|
|
if (shift_line)
|
|
vsc_ini_rcv_num++;
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale_enable[OSD2]) {
|
|
data32 = (((src_h - 1 + shift_line) & 0x1fff)
|
|
| ((src_w - 1) & 0x1fff) << 16);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCI_WH_M1, data32);
|
|
data32 = ((osd_hw.free_dst_data[OSD2].x_end & 0xfff) |
|
|
(osd_hw.free_dst_data[OSD2].x_start & 0xfff) << 16);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCO_H_START_END, data32);
|
|
data32 = ((osd_hw.free_dst_data[OSD2].y_end & 0xfff) |
|
|
(osd_hw.free_dst_data[OSD2].y_start & 0xfff) << 16);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCO_V_START_END, data32);
|
|
}
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale[OSD2].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(VPP_OSD_HSC_CTRL0, data32);
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale[OSD2].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;
|
|
}
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_VSC_CTRL0, data32);
|
|
data32 = 0x0;
|
|
if (osd_hw.free_scale_enable[OSD2]) {
|
|
data32 |= (bot_ini_phase & 0xffff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OSD_HSC_PHASE_STEP,
|
|
hf_phase_step, 0, 28);
|
|
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OSD_HSC_INI_PHASE, 0, 0, 16);
|
|
VSYNCOSD_WR_MPEG_REG_BITS(VPP_OSD_VSC_PHASE_STEP,
|
|
vf_phase_step, 0, 28);
|
|
VSYNCOSD_WR_MPEG_REG(VPP_OSD_VSC_INI_PHASE, data32);
|
|
}
|
|
remove_from_update_list(OSD2, DISP_FREESCALE_ENABLE);
|
|
}
|
|
|
|
static void osd2_update_coef(void)
|
|
{
|
|
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;
|
|
}
|
|
vf_coef = filter_table[use_v_filter_mode];
|
|
if (need_update_coef) {
|
|
if (vf_coef_wren) {
|
|
osd_reg_set_bits(VPP_OSD_SCALE_COEF_IDX, 0x0000, 0, 9);
|
|
for (i = 0; i < 33; i++)
|
|
osd_reg_write(VPP_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(VPP_OSD_SCALE_COEF_IDX, 0x0100, 0, 9);
|
|
for (i = 0; i < 33; i++)
|
|
osd_reg_write(VPP_OSD_SCALE_COEF, hf_coef[i]);
|
|
}
|
|
}
|
|
remove_from_update_list(OSD2, OSD_FREESCALE_COEF);
|
|
}
|
|
|
|
static void viu2_osd1_update_disp_freescale_enable(void)
|
|
{
|
|
/* do nothing */
|
|
|
|
remove_from_update_list(VIU2_OSD1, DISP_FREESCALE_ENABLE);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_coef(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_coef(void)
|
|
{
|
|
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(VPP_OSD_SCALE_COEF_IDX, 0x0000, 0, 9);
|
|
for (i = 0; i < 33; i++)
|
|
osd_reg_write(VPP_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(VPP_OSD_SCALE_COEF_IDX, 0x0100, 0, 9);
|
|
for (i = 0; i < 33; i++)
|
|
osd_reg_write(VPP_OSD_SCALE_COEF, hf_coef[i]);
|
|
}
|
|
}
|
|
remove_from_update_list(VIU2_OSD1, OSD_FREESCALE_COEF);
|
|
}
|
|
#endif
|
|
|
|
static void osd1_update_color_mode(void)
|
|
{
|
|
u32 data32 = 0;
|
|
if (osd_hw.color_info[OSD1] != NULL) {
|
|
data32 = (osd_hw.scan_mode == SCAN_MODE_INTERLACE) ? 2 : 0;
|
|
data32 |= VSYNCOSD_RD_MPEG_REG(VIU_OSD1_BLK0_CFG_W0)
|
|
& 0x30007040;
|
|
data32 |= osd_hw.fb_gem[OSD1].canvas_idx << 16;
|
|
if (!osd_hw.rotate[OSD1].on_off)
|
|
data32 |= OSD_DATA_LITTLE_ENDIAN << 15;
|
|
data32 |= osd_hw.color_info[OSD1]->hw_colormat << 2;
|
|
if (get_cpu_id().family_id < MESON_CPU_MAJOR_ID_GXTVBB) {
|
|
if (osd_hw.color_info[OSD1]->color_index
|
|
< COLOR_INDEX_YUV_422)
|
|
data32 |= 1 << 7; /* yuv enable */
|
|
}
|
|
/* osd_blk_mode */
|
|
data32 |= osd_hw.color_info[OSD1]->hw_blkmode << 8;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W0, data32);
|
|
}
|
|
remove_from_update_list(OSD1, OSD_COLOR_MODE);
|
|
}
|
|
static void osd2_update_color_mode(void)
|
|
{
|
|
u32 data32 = 0;
|
|
|
|
if (osd_hw.color_info[OSD2] != NULL) {
|
|
data32 = (osd_hw.scan_mode == SCAN_MODE_INTERLACE) ? 2 : 0;
|
|
data32 |= VSYNCOSD_RD_MPEG_REG(VIU_OSD2_BLK0_CFG_W0)
|
|
& 0x30007040;
|
|
data32 |= osd_hw.fb_gem[OSD2].canvas_idx << 16;
|
|
if (!osd_hw.rotate[OSD2].on_off)
|
|
data32 |= OSD_DATA_LITTLE_ENDIAN << 15;
|
|
data32 |= osd_hw.color_info[OSD2]->hw_colormat << 2;
|
|
if (get_cpu_id().family_id != MESON_CPU_MAJOR_ID_GXTVBB) {
|
|
if (osd_hw.color_info[OSD2]->color_index
|
|
< COLOR_INDEX_YUV_422)
|
|
data32 |= 1 << 7; /* yuv enable */
|
|
}
|
|
/* osd_blk_mode */
|
|
data32 |= osd_hw.color_info[OSD2]->hw_blkmode << 8;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W0, data32);
|
|
}
|
|
remove_from_update_list(OSD2, OSD_COLOR_MODE);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_color_mode(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_color_mode(void)
|
|
{
|
|
u32 data32 = 0;
|
|
if (osd_hw.color_info[VIU2_OSD1] != NULL) {
|
|
data32 = (osd_hw.scan_mode == SCAN_MODE_INTERLACE) ? 2 : 0;
|
|
data32 |= VSYNCOSD_RD_MPEG_REG(VIU2_OSD1_BLK0_CFG_W0)
|
|
& 0x30007040;
|
|
data32 |= osd_hw.fb_gem[VIU2_OSD1].canvas_idx << 16;
|
|
if (!osd_hw.rotate[VIU2_OSD1].on_off)
|
|
data32 |= OSD_DATA_LITTLE_ENDIAN << 15;
|
|
data32 |= osd_hw.color_info[VIU2_OSD1]->hw_colormat << 2;
|
|
|
|
/* osd_blk_mode */
|
|
data32 |= osd_hw.color_info[VIU2_OSD1]->hw_blkmode << 8;
|
|
VSYNCOSD_WR_MPEG_REG(VIU2_OSD1_BLK0_CFG_W0, data32);
|
|
}
|
|
remove_from_update_list(VIU2_OSD1, OSD_COLOR_MODE);
|
|
}
|
|
#endif
|
|
|
|
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(VIU_OSD1_CTRL_STAT, 1 << 0);
|
|
} else {
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD1_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(VIU_OSD2_CTRL_STAT,
|
|
1 << 0);
|
|
else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD2_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);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_enable(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_enable(void)
|
|
{
|
|
/* do nothing for VPP2_MISC */
|
|
if (osd_hw.enable[VIU2_OSD1] == ENABLE)
|
|
VSYNCOSD_SET_MPEG_REG_MASK(VIU2_OSD1_CTRL_STAT, 1 << 0);
|
|
else
|
|
VSYNCOSD_CLR_MPEG_REG_MASK(VIU2_OSD1_CTRL_STAT, 1 << 0);
|
|
|
|
remove_from_update_list(VIU2_OSD1, OSD_ENABLE);
|
|
}
|
|
#endif
|
|
|
|
static void osd1_update_disp_osd_reverse(void)
|
|
{
|
|
u32 val = 0;
|
|
|
|
switch (osd_hw.osd_reverse[OSD1]) {
|
|
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(VIU_OSD1_BLK0_CFG_W0, val, 28, 2);
|
|
remove_from_update_list(OSD1, DISP_OSD_REVERSE);
|
|
}
|
|
|
|
static void osd2_update_disp_osd_reverse(void)
|
|
{
|
|
u32 val = 0;
|
|
|
|
switch (osd_hw.osd_reverse[OSD2]) {
|
|
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(VIU_OSD2_BLK0_CFG_W0, val, 28, 2);
|
|
remove_from_update_list(OSD2, DISP_OSD_REVERSE);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_disp_osd_reverse(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_disp_osd_reverse(void)
|
|
{
|
|
u32 val = 0;
|
|
|
|
switch (osd_hw.osd_reverse[VIU2_OSD1]) {
|
|
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(VIU2_OSD1_BLK0_CFG_W0, val, 28, 2);
|
|
remove_from_update_list(VIU2_OSD1, DISP_OSD_REVERSE);
|
|
}
|
|
#endif
|
|
|
|
static void osd1_update_disp_osd_rotate(void)
|
|
{
|
|
#if 0
|
|
unsigned char x_rev = 0, y_rev = 0;
|
|
unsigned char bpp = 32;
|
|
unsigned int x_start;
|
|
unsigned int x_end;
|
|
unsigned int y_start;
|
|
unsigned int y_end;
|
|
unsigned int y_len_m1;
|
|
if (osd_hw.color_info[OSD1]->color_index <= COLOR_INDEX_08_PAL256)
|
|
bpp = 8;
|
|
else if (osd_hw.color_info[OSD1]->color_index <= COLOR_INDEX_16_565)
|
|
bpp = 16;
|
|
else if (osd_hw.color_info[OSD1]->color_index <= COLOR_INDEX_24_RGB)
|
|
bpp = 24;
|
|
else if (osd_hw.color_info[OSD1]->color_index <= COLOR_INDEX_32_ARGB)
|
|
bpp = 32;
|
|
switch (osd_hw.rotate[OSD1].angle) {
|
|
case 0:/* clockwise H flip (dst ) */
|
|
x_rev = 0;
|
|
y_rev = 0;
|
|
break;/* clockwise */
|
|
case 1:
|
|
y_rev = 1;
|
|
break;
|
|
case 2:/* anti-clockwise */
|
|
x_rev = 1;
|
|
break;
|
|
case 3:/* anti-clockwise H flip(dst) */
|
|
x_rev = 1;
|
|
y_rev = 1;
|
|
break;
|
|
}
|
|
x_start = osd_hw.rotation_pandata[OSD1].x_start;
|
|
x_end = osd_hw.rotation_pandata[OSD1].x_end;
|
|
y_start = osd_hw.rotation_pandata[OSD1].y_start;
|
|
y_end = osd_hw.rotation_pandata[OSD1].y_end;
|
|
y_len_m1 = y_end - y_start;
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_M8) {
|
|
osd_set_prot(
|
|
x_rev,
|
|
y_rev,
|
|
(bpp >> 3) - 1,
|
|
0, /* conv_422to444, */
|
|
OSD_DATA_LITTLE_ENDIAN,
|
|
HOLD_LINES,
|
|
x_start,
|
|
x_end,
|
|
y_start,
|
|
y_end,
|
|
y_len_m1,
|
|
Y_STEP,
|
|
PAT_START_PTR,
|
|
PAT_END_PTR,
|
|
PAT_VAL,
|
|
osd_hw.fb_gem[OSD1].canvas_idx,
|
|
CID_VALUE,
|
|
CID_MODE,
|
|
CUGT, /* urgent bit */
|
|
REQ_ONOFF_EN,
|
|
REQ_ON_MAX,
|
|
REQ_OFF_MIN,
|
|
OSD1,
|
|
osd_hw.rotate[OSD1].on_off);
|
|
}
|
|
#endif
|
|
remove_from_update_list(OSD1, DISP_OSD_ROTATE);
|
|
}
|
|
|
|
static void osd2_update_disp_osd_rotate(void)
|
|
{
|
|
#if 0
|
|
unsigned char x_rev = 0, y_rev = 0;
|
|
unsigned char bpp = 32;
|
|
unsigned int x_start;
|
|
unsigned int x_end;
|
|
unsigned int y_start;
|
|
unsigned int y_end;
|
|
unsigned int y_len_m1;
|
|
if (osd_hw.color_info[OSD2]->color_index <= COLOR_INDEX_08_PAL256)
|
|
bpp = 8;
|
|
else if (osd_hw.color_info[OSD2]->color_index <= COLOR_INDEX_16_565)
|
|
bpp = 16;
|
|
else if (osd_hw.color_info[OSD2]->color_index <= COLOR_INDEX_24_RGB)
|
|
bpp = 24;
|
|
else if (osd_hw.color_info[OSD2]->color_index <= COLOR_INDEX_32_ARGB)
|
|
bpp = 32;
|
|
switch (osd_hw.rotate[OSD2].angle) {
|
|
case 0:/* clockwise H flip (dst ) */
|
|
x_rev = 0;
|
|
y_rev = 0;
|
|
break;/* clockwise */
|
|
case 1:
|
|
y_rev = 1;
|
|
break;
|
|
case 2:/* anti-clockwise */
|
|
x_rev = 1;
|
|
break;
|
|
case 3:/* anti-clockwise H flip(dst) */
|
|
x_rev = 1;
|
|
y_rev = 1;
|
|
break;
|
|
}
|
|
x_start = osd_hw.rotation_pandata[OSD2].x_start;
|
|
x_end = osd_hw.rotation_pandata[OSD2].x_end;
|
|
y_start = osd_hw.rotation_pandata[OSD2].y_start;
|
|
y_end = osd_hw.rotation_pandata[OSD2].y_end;
|
|
y_len_m1 = y_end - y_start;
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_M8) {
|
|
osd_set_prot(
|
|
x_rev,
|
|
y_rev,
|
|
(bpp >> 3) - 1, /* bytes_per_pixel, */
|
|
0, /* conv_422to444, */
|
|
OSD_DATA_LITTLE_ENDIAN,
|
|
HOLD_LINES,
|
|
x_start,
|
|
x_end,
|
|
y_start,
|
|
y_end,
|
|
y_len_m1,
|
|
Y_STEP,
|
|
PAT_START_PTR,
|
|
PAT_END_PTR,
|
|
PAT_VAL,
|
|
osd_hw.fb_gem[OSD2].canvas_idx,
|
|
CID_VALUE,
|
|
CID_MODE,
|
|
CUGT, /* urgent bit */
|
|
REQ_ONOFF_EN,
|
|
REQ_ON_MAX,
|
|
REQ_OFF_MIN,
|
|
OSD2,
|
|
osd_hw.rotate[OSD2].on_off);
|
|
}
|
|
#endif
|
|
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 osd1_update_color_key(void)
|
|
{
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_TCOLOR_AG0, osd_hw.color_key[OSD1]);
|
|
remove_from_update_list(OSD1, OSD_COLOR_KEY);
|
|
}
|
|
|
|
static void osd2_update_color_key(void)
|
|
{
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_TCOLOR_AG0, osd_hw.color_key[OSD2]);
|
|
remove_from_update_list(OSD2, OSD_COLOR_KEY);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_color_key(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_color_key(void)
|
|
{
|
|
VSYNCOSD_WR_MPEG_REG(VIU2_OSD1_TCOLOR_AG0, osd_hw.color_key[VIU2_OSD1]);
|
|
remove_from_update_list(VIU2_OSD1, OSD_COLOR_KEY);
|
|
}
|
|
#endif
|
|
|
|
static void osd1_update_color_key_enable(void)
|
|
{
|
|
u32 data32;
|
|
data32 = VSYNCOSD_RD_MPEG_REG(VIU_OSD1_BLK0_CFG_W0);
|
|
data32 &= ~(1 << 6);
|
|
data32 |= (osd_hw.color_key_enable[OSD1] << 6);
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W0, data32);
|
|
remove_from_update_list(OSD1, OSD_COLOR_KEY_ENABLE);
|
|
}
|
|
|
|
static void osd2_update_color_key_enable(void)
|
|
{
|
|
u32 data32;
|
|
data32 = VSYNCOSD_RD_MPEG_REG(VIU_OSD2_BLK0_CFG_W0);
|
|
data32 &= ~(1 << 6);
|
|
data32 |= (osd_hw.color_key_enable[OSD2] << 6);
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W0, data32);
|
|
remove_from_update_list(OSD2, OSD_COLOR_KEY_ENABLE);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_color_key_enable(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_color_key_enable(void)
|
|
{
|
|
u32 data32;
|
|
data32 = VSYNCOSD_RD_MPEG_REG(VIU2_OSD1_BLK0_CFG_W0);
|
|
data32 &= ~(1 << 6);
|
|
data32 |= (osd_hw.color_key_enable[VIU2_OSD1] << 6);
|
|
VSYNCOSD_WR_MPEG_REG(VIU2_OSD1_BLK0_CFG_W0, data32);
|
|
remove_from_update_list(VIU2_OSD1, OSD_COLOR_KEY_ENABLE);
|
|
}
|
|
#endif
|
|
|
|
static void osd1_update_gbl_alpha(void)
|
|
{
|
|
u32 data32;
|
|
data32 = VSYNCOSD_RD_MPEG_REG(VIU_OSD1_CTRL_STAT);
|
|
data32 &= ~(0x1ff << 12);
|
|
data32 |= osd_hw.gbl_alpha[OSD1] << 12;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_CTRL_STAT, data32);
|
|
remove_from_update_list(OSD1, OSD_GBL_ALPHA);
|
|
}
|
|
|
|
static void osd2_update_gbl_alpha(void)
|
|
{
|
|
u32 data32;
|
|
data32 = VSYNCOSD_RD_MPEG_REG(VIU_OSD2_CTRL_STAT);
|
|
data32 &= ~(0x1ff << 12);
|
|
data32 |= osd_hw.gbl_alpha[OSD2] << 12;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_CTRL_STAT, data32);
|
|
remove_from_update_list(OSD2, OSD_GBL_ALPHA);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_gbl_alpha(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_gbl_alpha(void)
|
|
{
|
|
u32 data32;
|
|
data32 = VSYNCOSD_RD_MPEG_REG(VIU2_OSD1_CTRL_STAT);
|
|
data32 &= ~(0x1ff << 12);
|
|
data32 |= osd_hw.gbl_alpha[VIU2_OSD1] << 12;
|
|
VSYNCOSD_WR_MPEG_REG(VIU2_OSD1_CTRL_STAT, data32);
|
|
remove_from_update_list(VIU2_OSD1, OSD_GBL_ALPHA);
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
static void viu2_osd1_update_order(void)
|
|
{
|
|
/* do nothing */
|
|
|
|
remove_from_update_list(VIU2_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_BLK0_CFG_W4, data32);
|
|
}
|
|
}
|
|
|
|
static void osd1_basic_update_disp_geometry(void)
|
|
{
|
|
u32 data32;
|
|
|
|
if (get_cpu_id().family_id >= 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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_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(VIU_OSD1_BLK0_CFG_W2, data32);
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_M8)
|
|
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_Y_START_END, data32);
|
|
} 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(VIU_OSD1_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(VIU_OSD1_BLK0_CFG_W2, data32);
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_M8)
|
|
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_Y_START_END, data32);
|
|
} else {
|
|
/* normal mode */
|
|
data32 = (osd_hw.pandata[OSD1].x_start & 0x1fff)
|
|
| (osd_hw.pandata[OSD1].x_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W1, data32);
|
|
data32 = (osd_hw.pandata[OSD1].y_start & 0x1fff)
|
|
| (osd_hw.pandata[OSD1].y_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_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 osd2_update_disp_geometry(void)
|
|
{
|
|
u32 data32;
|
|
data32 = (osd_hw.dispdata[OSD2].x_start & 0xfff)
|
|
| (osd_hw.dispdata[OSD2].x_end & 0xfff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W3 , data32);
|
|
if (osd_hw.scan_mode == SCAN_MODE_INTERLACE)
|
|
data32 = ((osd_hw.dispdata[OSD2].y_start >> 1) & 0xfff)
|
|
| ((((osd_hw.dispdata[OSD2].y_end + 1) >> 1) - 1)
|
|
& 0xfff) << 16;
|
|
else
|
|
data32 = (osd_hw.dispdata[OSD2].y_start & 0xfff)
|
|
| (osd_hw.dispdata[OSD2].y_end & 0xfff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W4, data32);
|
|
if (osd_hw.scale[OSD2].h_enable || osd_hw.scale[OSD2].v_enable) {
|
|
#if defined(CONFIG_FB_OSD2_CURSOR)
|
|
data32 = (osd_hw.pandata[OSD2].x_start & 0x1fff)
|
|
| (osd_hw.pandata[OSD2].x_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W1, data32);
|
|
data32 = (osd_hw.pandata[OSD2].y_start & 0x1fff)
|
|
| (osd_hw.pandata[OSD2].y_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W2, data32);
|
|
#else
|
|
data32 = (osd_hw.scaledata[OSD2].x_start & 0x1fff) |
|
|
(osd_hw.scaledata[OSD2].x_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W1, data32);
|
|
data32 = ((osd_hw.scaledata[OSD2].y_start
|
|
+ osd_hw.pandata[OSD2].y_start) & 0x1fff)
|
|
| ((osd_hw.scaledata[OSD2].y_end
|
|
+ osd_hw.pandata[OSD2].y_start) & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W2, data32);
|
|
#endif
|
|
} else if (osd_hw.free_scale_enable[OSD2]
|
|
&& (osd_hw.free_scale_data[OSD2].x_end > 0)
|
|
&& (osd_hw.free_scale_data[OSD2].y_end > 0)) {
|
|
/* enable osd free scale */
|
|
data32 = (osd_hw.free_scale_data[OSD2].x_start & 0x1fff)
|
|
| (osd_hw.free_scale_data[OSD2].x_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W1, data32);
|
|
data32 = ((osd_hw.free_scale_data[OSD2].y_start
|
|
+ osd_hw.pandata[OSD2].y_start) & 0x1fff)
|
|
| ((osd_hw.free_scale_data[OSD2].y_end
|
|
+ osd_hw.pandata[OSD2].y_start) & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W2, data32);
|
|
} else {
|
|
data32 = (osd_hw.pandata[OSD2].x_start & 0x1fff)
|
|
| (osd_hw.pandata[OSD2].x_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W1, data32);
|
|
data32 = (osd_hw.pandata[OSD2].y_start & 0x1fff)
|
|
| (osd_hw.pandata[OSD2].y_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W2, data32);
|
|
}
|
|
remove_from_update_list(OSD2, DISP_GEOMETRY);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_disp_geometry(void)
|
|
{
|
|
}
|
|
#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(VIU2_OSD1_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(VIU2_OSD1_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(VIU2_OSD1_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(VIU2_OSD1_BLK0_CFG_W2, data32);
|
|
|
|
remove_from_update_list(VIU2_OSD1, DISP_GEOMETRY);
|
|
}
|
|
#endif
|
|
|
|
static void osd1_update_disp_3d_mode(void)
|
|
{
|
|
/*step 1 . set pan data */
|
|
u32 data32;
|
|
if (osd_hw.mode_3d[OSD1].left_right == OSD_LEFT) {
|
|
data32 = (osd_hw.mode_3d[OSD1].l_start & 0x1fff)
|
|
| (osd_hw.mode_3d[OSD1].l_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W1, data32);
|
|
} else {
|
|
data32 = (osd_hw.mode_3d[OSD1].r_start & 0x1fff)
|
|
| (osd_hw.mode_3d[OSD1].r_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W1, data32);
|
|
}
|
|
osd_hw.mode_3d[OSD1].left_right ^= 1;
|
|
}
|
|
|
|
static void osd2_update_disp_3d_mode(void)
|
|
{
|
|
u32 data32;
|
|
if (osd_hw.mode_3d[OSD2].left_right == OSD_LEFT) {
|
|
data32 = (osd_hw.mode_3d[OSD2].l_start & 0x1fff)
|
|
| (osd_hw.mode_3d[OSD2].l_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W1, data32);
|
|
} else {
|
|
data32 = (osd_hw.mode_3d[OSD2].r_start & 0x1fff)
|
|
| (osd_hw.mode_3d[OSD2].r_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK0_CFG_W1, data32);
|
|
}
|
|
osd_hw.mode_3d[OSD2].left_right ^= 1;
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
static void viu2_osd1_update_disp_3d_mode(void)
|
|
{
|
|
}
|
|
#else
|
|
static void viu2_osd1_update_disp_3d_mode(void)
|
|
{
|
|
u32 data32;
|
|
if (osd_hw.mode_3d[VIU2_OSD1].left_right == OSD_LEFT) {
|
|
data32 = (osd_hw.mode_3d[VIU2_OSD1].l_start & 0x1fff)
|
|
| (osd_hw.mode_3d[VIU2_OSD1].l_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU2_OSD1_BLK0_CFG_W1, data32);
|
|
} else {
|
|
data32 = (osd_hw.mode_3d[VIU2_OSD1].r_start & 0x1fff)
|
|
| (osd_hw.mode_3d[VIU2_OSD1].r_end & 0x1fff) << 16;
|
|
VSYNCOSD_WR_MPEG_REG(VIU2_OSD1_BLK0_CFG_W1, data32);
|
|
}
|
|
osd_hw.mode_3d[VIU2_OSD1].left_right ^= 1;
|
|
}
|
|
#endif
|
|
|
|
void osd_hist_enable(u32 osd_index)
|
|
{
|
|
#ifdef CONFIG_AML_MESON_G12A
|
|
if (get_cpu_id().family_id >= MESON_CPU_MAJOR_ID_G12A)
|
|
VSYNCOSD_WR_MPEG_REG(VI_HIST_CTRL, 0x1801);
|
|
else
|
|
#endif
|
|
{
|
|
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));
|
|
}
|
|
|
|
int osd_get_hist_stat(u32 *hist_result)
|
|
{
|
|
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]);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_AML_T7_DISPLAY
|
|
void osd_init_hw_viu2(void)
|
|
{
|
|
}
|
|
#else
|
|
#ifdef CONFIG_AML_MESON_G12A
|
|
void osd_init_hw_viu2(void)
|
|
{
|
|
u32 group, idx, data32, holdline = 4, reverse_val = 0;
|
|
char *osd_reverse;
|
|
unsigned long s = 0;
|
|
|
|
osd_reverse = getenv("osd_reverse");
|
|
s = getenv_ulong("viu2_hold_line", 10, 0);
|
|
if (s)
|
|
holdline = s;
|
|
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[VIU2_OSD1] = 0;
|
|
|
|
osd_vpu_power_on_viu2();
|
|
|
|
osd_reg_write(VPP2_OFIFO_SIZE, 0x7ff00800);
|
|
|
|
/* init osd fifo control register */
|
|
/* set DDR request priority to be urgent */
|
|
data32 = 1;
|
|
/* hold_fifo_lines */
|
|
data32 |= holdline << 5;
|
|
/* 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(VIU2_OSD1_FIFO_CTRL_STAT, data32);
|
|
|
|
/* disable osd */
|
|
data32 = 0x0 << 0;
|
|
data32 |= OSD_GLOBAL_ALPHA_DEF << 12;
|
|
data32 |= 0x80000000;
|
|
osd_reg_write(VIU2_OSD1_CTRL_STAT , data32);
|
|
|
|
/* set replaced_alpha */
|
|
data32 = 0x1 << 14;
|
|
data32 |= 0xff << 6;
|
|
osd_reg_write(VIU2_OSD1_CTRL_STAT2 , data32);
|
|
osd_hw.enable[VIU2_OSD1] = DISABLE;
|
|
|
|
osd_hw.fb_gem[VIU2_OSD1].canvas_idx = OSD4_CANVAS_INDEX;
|
|
osd_hw.gbl_alpha[VIU2_OSD1] = OSD_GLOBAL_ALPHA_DEF;
|
|
osd_hw.color_info[VIU2_OSD1] = NULL;
|
|
osd_hw.color_key[VIU2_OSD1] = 0xffffffff;
|
|
osd_hw.scale[VIU2_OSD1].h_enable = osd_hw.scale[VIU2_OSD1].v_enable = 0;
|
|
osd_hw.mode_3d[VIU2_OSD1].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[VIU2_OSD1] = reverse_val;
|
|
|
|
osd_hw.rotation_pandata[VIU2_OSD1].x_start = 0;
|
|
osd_hw.rotation_pandata[VIU2_OSD1].y_start = 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
static void set_vpp_super_position(void)
|
|
{
|
|
#define PREBLD_SR0_VD1_SCALER (1 << 1)
|
|
#define DNLP_SR1_CM (1 << 3)
|
|
|
|
if ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_G12A) ||
|
|
(get_cpu_id().family_id == MESON_CPU_MAJOR_ID_G12B) ||
|
|
(get_cpu_id().family_id == MESON_CPU_MAJOR_ID_SM1))
|
|
osd_reg_set_mask(VPP_MISC, PREBLD_SR0_VD1_SCALER);
|
|
else if ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_TL1) ||
|
|
(get_cpu_id().family_id == MESON_CPU_MAJOR_ID_TM2) ||
|
|
(get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5) ||
|
|
(get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5D))
|
|
osd_reg_set_mask(VPP_MISC, DNLP_SR1_CM);
|
|
}
|
|
|
|
static void independ_path_default_regs(void)
|
|
{
|
|
/* 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);
|
|
}
|
|
|
|
void osd_init_hw(void)
|
|
{
|
|
u32 group, idx, data32, data2, holdline = 8, reverse_val = 0;
|
|
char *osd_reverse;
|
|
u32 ofifo_size = 0xfff;
|
|
unsigned long s = 0;
|
|
|
|
osd_reverse = getenv("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_vpu_power_on();
|
|
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5W)
|
|
osd_hw.path_ctrl_independ = 1;
|
|
|
|
if (osd_hw.path_ctrl_independ)
|
|
independ_path_default_regs();
|
|
|
|
/* here we will init default value ,these value only set once . */
|
|
if (!logo_loaded) {
|
|
/* 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);
|
|
if (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5D)
|
|
ofifo_size = 0x77f;
|
|
data32 |= (ofifo_size << 20);
|
|
data32 |= (ofifo_size + 1);
|
|
osd_reg_write(VPP_OFIFO_SIZE, data32);
|
|
}
|
|
|
|
/* init osd fifo control register */
|
|
/* set DDR request priority to be urgent */
|
|
data32 = 1;
|
|
if ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_M6TV)
|
|
|| (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_MTVD)) {
|
|
data32 |= 18 << 5; /* hold_fifo_lines */
|
|
} else if (osd_hw.osd_ver == OSD_SIMPLE) {
|
|
data32 &= ~(0x1f << 5); /* bit[9:5] HOLD_FIFO_LINES */
|
|
data32 |= 0x18 << 5;
|
|
} else {
|
|
s = getenv_ulong("viu1_hold_line", 10, 0);
|
|
if (s) {
|
|
holdline = s;
|
|
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) {
|
|
data32 |= 1 << 10;
|
|
data32 |= 1 << 31;
|
|
} else
|
|
data32 |= 3 << 10;
|
|
|
|
if (get_cpu_id().family_id >= 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 ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_TXL)
|
|
|| (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_TXLX))
|
|
data32 |= 64 << 12;
|
|
else
|
|
data32 |= 32 << 12;
|
|
data2 |= 32 << 12;
|
|
osd_reg_write(VIU_OSD1_FIFO_CTRL_STAT, data32);
|
|
osd_reg_write(VIU_OSD2_FIFO_CTRL_STAT, data2);
|
|
|
|
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);
|
|
/* just disable osd to avoid booting hang up */
|
|
data32 = 0x0 << 0;
|
|
data32 |= OSD_GLOBAL_ALPHA_DEF << 12;
|
|
osd_reg_write(VIU_OSD1_CTRL_STAT , data32);
|
|
osd_reg_write(VIU_OSD2_CTRL_STAT , data32);
|
|
|
|
/* set replaced_alpha */
|
|
data32 = 0x1 << 14;
|
|
data32 |= 0xff << 6;
|
|
osd_reg_write(VIU_OSD1_CTRL_STAT2 , data32);
|
|
osd_reg_write(VIU_OSD2_CTRL_STAT2 , data32);
|
|
logo_loaded = 1;
|
|
}
|
|
|
|
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();
|
|
osd_hw.order = OSD_ORDER_01;
|
|
osd_hw.enable[OSD2] = osd_hw.enable[OSD1] = DISABLE;
|
|
osd_hw.fb_gem[OSD1].canvas_idx = OSD1_CANVAS_INDEX;
|
|
osd_hw.fb_gem[OSD2].canvas_idx = OSD2_CANVAS_INDEX;
|
|
osd_hw.gbl_alpha[OSD1] = OSD_GLOBAL_ALPHA_DEF;
|
|
osd_hw.gbl_alpha[OSD2] = OSD_GLOBAL_ALPHA_DEF;
|
|
osd_hw.color_info[OSD1] = NULL;
|
|
osd_hw.color_info[OSD2] = NULL;
|
|
osd_hw.color_key[OSD1] = osd_hw.color_key[OSD2] = 0xffffffff;
|
|
osd_hw.free_scale_enable[OSD1] = osd_hw.free_scale_enable[OSD2] = 0;
|
|
osd_hw.scale[OSD1].h_enable = osd_hw.scale[OSD1].v_enable = 0;
|
|
osd_hw.scale[OSD2].h_enable = osd_hw.scale[OSD2].v_enable = 0;
|
|
osd_hw.mode_3d[OSD2].enable = osd_hw.mode_3d[OSD1].enable = 0;
|
|
osd_hw.block_mode[OSD1] = osd_hw.block_mode[OSD2] = 0;
|
|
osd_hw.free_scale[OSD1].h_enable = 0;
|
|
osd_hw.free_scale[OSD1].h_enable = 0;
|
|
osd_hw.free_scale[OSD2].v_enable = 0;
|
|
osd_hw.free_scale[OSD2].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.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.antiflicker_mode = 0;
|
|
if (get_cpu_id().family_id >= 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_mode[OSD1] = 1;
|
|
osd_hw.free_scale_mode[OSD2] = 1;
|
|
if ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_GXM))
|
|
osd_reg_write(VPP_OSD_SC_DUMMY_DATA, 0x00202000);
|
|
else if (get_cpu_id().family_id ==
|
|
MESON_CPU_MAJOR_ID_GXTVBB)
|
|
osd_reg_write(VPP_OSD_SC_DUMMY_DATA, 0xff);
|
|
else
|
|
osd_reg_write(VPP_OSD_SC_DUMMY_DATA, 0x00808000);
|
|
} else {
|
|
osd_hw.free_scale_mode[OSD1] = 0;
|
|
osd_hw.free_scale_mode[OSD2] = 0;
|
|
}
|
|
memset(osd_hw.rotate, 0, sizeof(struct osd_rotate_s) * HW_OSD_COUNT);
|
|
if ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_G12A) ||
|
|
((get_cpu_id().family_id == 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 (get_cpu_id().family_id == MESON_CPU_MAJOR_ID_T5W)
|
|
osd_hw.mif_linear = 1;
|
|
|
|
return;
|
|
}
|
|
|
|
|