gk7205v200-uboot/product/osd/vo/gk7205v200/vou_drv.c

1335 lines
46 KiB
C
Raw Normal View History

2025-08-07 17:13:54 +08:00
/*
* Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
*/
#include "vou_drv.h"
#include "type.h"
#include "vou_reg.h"
#include "vou_def.h"
#include "vou_hal.h"
#include "vou_coef_org.h"
#define VO_DEV_MAX_NUM 1
#define VO_LAYER_MAX_NUM 1
#define VO_SD_VTTH_WATERLINE 100
#define VO_HD_VTTH_WATERLINE 240
#define VO_BACKGROUD_BLACK 0x8080
#define VO_BACKGROUD_GREEN 0x804D3A42
#define VO_BACKGROUD_WHITE 0x3fffffff
#define VO_BACKGROUD_DEFAULT VO_BACKGROUD_WHITE
#define max2(x, y) ((x) > (y) ? (x) : (y))
#define min2(x, y) ((x) < (y) ? (x) : (y))
#define clip_min(x, min) (((x) >= (min)) ? (x) : (min))
static gk_u32 rgb_to_yuv_full(gk_u32 rgb)
{
gk_u16 y, u, v;
gk_u16 r, g, b;
gk_u16 py_temp, pcb_temp, pcr_temp;
r = rgb_r(rgb);
g = rgb_g(rgb);
b = rgb_b(rgb);
/* to calculate rgb to yc, the numbers is from algorithm, not magic numbers */
py_temp = (gk_u16)(((r * 76 + g * 150 + b * 29) >> 8) * 4);
pcb_temp = (gk_u16)(clip_min(((((b * 130 - r * 44) - g * 86) >> 8) + 128), 0) * 4);
pcr_temp = (gk_u16)(clip_min(((((r * 130 - g * 109) - b * 21) >> 8) + 128), 0) * 4);
/* value 0 - 1023 */
y = max2(min2(py_temp, 1023), 0);
u = max2(min2(pcb_temp, 1023), 0);
v = max2(min2(pcr_temp, 1023), 0);
return yuv(y, u, v);
}
/* vou interrupt mask type */
typedef enum {
VO_INTMSK_NONE = 0,
VO_INTMSK_DHD0_VTTHD1 = 0x1,
VO_INTMSK_DHD0_VTTHD2 = 0x2,
VO_INTMSK_DHD0_VTTHD3 = 0x4,
VO_INTMSK_DHD0_UFINT = 0x8,
VO_INTMSK_DHD1_VTTHD1 = 0x10,
VO_INTMSK_DHD1_VTTHD2 = 0x20,
VO_INTMSK_DHD1_VTTHD3 = 0x40,
VO_INTMSK_DHD1_UFINT = 0x80,
VO_INTMSK_DSD_VTTHD1 = 0x100,
VO_INTMSK_DSD_VTTHD2 = 0x200,
VO_INTMSK_DSD_VTTHD3 = 0x400,
VO_INTMSK_DSD_UFINT = 0x800,
VO_INTMSK_B0_ERR = 0x1000,
VO_INTMSK_B1_ERR = 0x2000,
VO_INTMSK_B2_ERR = 0x4000,
VO_INTMSK_WBC_DHDOVER = 0x8000,
VO_INTREPORT_ALL = 0xffffffff
} vo_int_mask;
typedef struct {
gk_bool enable;
gk_u32 bk_grd;
vo_intf_type intf_type;
vo_intf_sync out_sync;
hal_disp_pixel_format pixel_fmt;
} hal_dev_config;
typedef struct {
gk_u32 bk_grd;
} hal_layer_config;
typedef struct {
gk_s32 luma;
gk_s32 cont;
gk_s32 hue;
gk_s32 satu;
} hal_csc_value;
typedef struct {
gk_u32 base_phys;
gk_void *base_virt;
gk_u32 hor;
gk_u32 ver422;
gk_u32 ver420;
gk_u32 lut;
gk_u32 gam;
gk_u32 acc;
} hal_coef_addr;
vo_user_intfsync_info g_user_intfsync_info = {
.dev_div = 1,
.clk_reverse = GK_TRUE,
.user_intf_sync_attr = {
.clk_source = VO_CLK_SOURCE_LCDMCLK,
.lcd_m_clk_div = 0xC5E41,
}
};
/* user time default value */
hal_disp_syncinfo g_user_sync_timing = {
.synm = 0,
.iop = 1,
.intfb = 1,
.vact = 480,
.vbb = 4,
.vfb = 8,
.hact = 320,
.hbb = 8,
.hfb = 38,
.hmid = 1,
.bvact = 240,
.bvbb = 14,
.bvfb = 9,
.hpw = 4,
.vpw = 4,
.idv = 0,
.ihs = 1,
.ivs = 1,
};
hal_disp_syncinfo g_sync_timing[VO_OUTPUT_BUTT] = {
/* synm, iop, itf, vact, vbb, vfb, hact, hbb, hfb, hmid,bvact,bvbb, bvfb, hpw, vpw,idv, ihs, ivs */
{ 0, 0, 0, 288, 22, 2, 720, 132, 12, 1, 288, 23, 2, 126, 3, 0, 0, 0 }, /* 576I(PAL) */
{ 0, 0, 0, 240, 18, 4, 720, 119, 19, 1, 240, 19, 4, 124, 3, 0, 0, 0 }, /* 480I(NTSC) */
{ 0, 1, 1, 1080, 41, 4, 1920, 192, 638, 1, 1, 1, 1, 44, 5, 0, 0, 0 }, /* 1080P@24Hz */
{ 0, 1, 1, 1080, 41, 4, 1920, 192, 528, 1, 1, 1, 1, 44, 5, 0, 0, 0 }, /* 1080P@25Hz */
{ 0, 1, 1, 1080, 41, 4, 1920, 192, 88, 1, 1, 1, 1, 44, 5, 0, 0, 0 }, /* 1080P@30Hz */
{ 0, 1, 1, 720, 25, 5, 1280, 260, 440, 1, 1, 1, 1, 40, 5, 0, 0, 0 }, /* 720P@50Hz */
{ 0, 1, 1, 720, 25, 5, 1280, 260, 110, 1, 1, 1, 1, 40, 5, 0, 0, 0 }, /* 720P@60Hz */
{ 0, 0, 1, 540, 20, 2, 1920, 192, 528, 1128, 540, 21, 2, 44, 5, 0, 0, 0 }, /* 1080I@50Hz */
{ 0, 0, 1, 540, 20, 2, 1920, 192, 88, 908, 540, 21, 2, 44, 5, 0, 0, 0 }, /* 1080I@60Hz */
{ 0, 1, 1, 1080, 41, 4, 1920, 192, 528, 1, 1, 1, 1, 44, 5, 0, 0, 0 }, /* 1080P@50Hz */
{ 0, 1, 1, 1080, 41, 4, 1920, 192, 88, 1, 1, 1, 1, 44, 5, 0, 0, 0 }, /* 1080P@60Hz */
{ 1, 1, 1, 576, 44, 5, 720, 132, 12, 1, 1, 1, 1, 64, 5, 0, 0, 0 }, /* 576P@50Hz */
{ 1, 1, 1, 480, 36, 9, 720, 122, 16, 1, 1, 1, 1, 62, 6, 0, 0, 0 }, /* 480P@60Hz */
{ 1, 1, 2, 600, 27, 1, 800, 216, 40, 1, 1, 1, 1, 128, 4, 0, 0, 0 }, /* 800*600@60Hz VGA@60Hz */
{ 1, 1, 2, 768, 35, 3, 1024, 296, 24, 1, 1, 1, 1, 136, 6, 0, 1, 1 }, /* 1024x768@60Hz */
{ 1, 1, 2, 1024, 41, 1, 1280, 360, 48, 1, 1, 1, 1, 112, 3, 0, 0, 0 }, /* 1280x1024@60Hz */
{ 1, 1, 2, 768, 27, 3, 1366, 356, 70, 1, 1, 1, 1, 143, 3, 0, 0, 0 }, /* 1366x768@60Hz */
{ 1, 1, 2, 900, 31, 3, 1440, 384, 80, 1, 1, 1, 1, 152, 6, 0, 1, 0 }, /* 1440x900@60Hz */
{ 1, 1, 2, 800, 28, 3, 1280, 328, 72, 1, 1, 1, 1, 128, 6, 0, 1, 0 }, /* 1280*800@60Hz VGA@60Hz */
{ 1, 1, 2, 1200, 49, 1, 1600, 496, 64, 1, 1, 1, 1, 192, 3, 0, 0, 0 }, /* 1600*1200@60Hz */
{ 1, 1, 2, 1050, 36, 3, 1680, 456, 104, 1, 1, 1, 1, 176, 6, 0, 1, 0 }, /* 1680*1050@60Hz */
/* 1920*1200@60Hz CVT (reduced blanking) */
{ 1, 1, 2, 1200, 32, 3, 1920, 112, 48, 1, 1, 1, 1, 32, 6, 0, 0, 1 },
{ 1, 1, 2, 480, 35, 10, 640, 144, 16, 1, 1, 1, 1, 96, 2, 0, 1, 1 }, /* 640*480@60Hz CVT */
{ 0, 0, 0, 288, 22, 2, 960, 176, 16, 1, 288, 23, 2, 168, 3, 0, 0, 0 }, /* 960H(PAL) */
{ 0, 0, 0, 240, 18, 4, 960, 163, 21, 1, 240, 19, 4, 168, 3, 0, 0, 0 }, /* 960H(NTSC) */
{ 0, 1, 1, 2160, 72, 8, 1920, 192, 88, 1, 1, 1, 1, 44, 5, 0, 0, 0 }, /* 1920*2160@30Hz */
{ 1, 1, 2, 1440, 39, 2, 2560, 112, 48, 1, 1, 1, 1, 32, 5, 0, 0, 0 }, /* 2560*1440@30Hz */
{ 1, 1, 2, 1440, 39, 2, 2560, 112, 48, 1, 1, 1, 1, 32, 5, 0, 0, 0 }, /* 2560*1440@60Hz */
/* 2560*1600@60Hz CVT (reduced blanking) */
{ 0, 1, 2, 1600, 43, 3, 2560, 112, 48, 1, 1, 1, 1, 32, 6, 0, 0, 1 },
{ 0, 1, 1, 2160, 82, 8, 3840, 384, 1276, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 3840*2160@24Hz */
{ 0, 1, 1, 2160, 82, 8, 3840, 384, 1056, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 3840*2160@25Hz */
{ 0, 1, 1, 2160, 82, 8, 3840, 384, 176, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 3840*2160@30Hz */
{ 0, 1, 1, 2160, 82, 8, 3840, 384, 1056, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 3840*2160@50Hz */
{ 0, 1, 1, 2160, 82, 8, 3840, 384, 176, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 3840*2160@60Hz */
{ 0, 1, 1, 2160, 82, 8, 4096, 384, 1020, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 4096x2160@24 */
{ 0, 1, 1, 2160, 82, 8, 4096, 216, 968, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 4096x2160@25 */
{ 0, 1, 1, 2160, 82, 8, 4096, 216, 88, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 4096x2160@30 */
{ 0, 1, 1, 2160, 82, 8, 4096, 216, 968, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 4096x2160@50 */
{ 0, 1, 1, 2160, 82, 8, 4096, 216, 88, 1, 1, 1, 1, 88, 10, 0, 0, 0 }, /* 4096x2160@60 */
{ 0, 1, 1, 240, 15, 9, 320, 65, 7, 1, 240, 14, 9, 1, 1, 0, 0, 0 }, /* 320X240@60 8bit LCD */
{ 0, 1, 1, 240, 2, 2, 320, 5, 10, 1, 1, 1, 1, 10, 1, 0, 0, 0 }, /* 320X240@50 6bit LCD */
{ 0, 1, 1, 320, 10, 4, 240, 30, 10, 1, 1, 1, 1, 10, 2, 0, 0, 0 }, /* 240X320@50 6bit LCD */
{ 0, 1, 1, 320, 2, 2, 240, 20, 10, 1, 1, 1, 1, 2, 1, 0, 0, 0 }, /* 240X320@60 16bit LCD */
{ 0, 1, 1, 600, 23, 12, 800, 210, 46, 1, 1, 1, 1, 2, 1, 0, 0, 0 }, /* 800X600@60 24bit LCD */
{ 0, 1, 1, 1280, 24, 8, 720, 123, 99, 1, 1, 1, 1, 24, 4, 0, 0, 0 }, /* 720 x1280 at 60 hz */
{ 0, 1, 1, 1920, 36, 16, 1080, 28, 130, 1, 1, 1, 1, 8, 10, 0, 0, 0 }, /* 1080 x1920 at 60 hz */
{ 0, 1, 1, 4320, 64, 16, 7680, 768, 552, 1, 1, 1, 1, 176, 20, 0, 0, 0 }, /* 7680x4320@30 */
{} /* user */
};
static hal_dev_config g_hal_dev_cfg[VO_DEV_MAX_NUM] = {
{
.enable = GK_FALSE,
.bk_grd = VO_BACKGROUD_DEFAULT,
.intf_type = VO_INTF_BT1120 | VO_INTF_LCD,
.out_sync = VO_OUTPUT_1080P30,
.pixel_fmt = HAL_INPUTFMT_Y_CB_CR_SEMIPLANAR_422,
}
};
gk_void vo_drv_board_init(gk_void)
{
hal_vo_init();
vo_drv_default_setting();
}
gk_void vo_drv_int_reg_up_mode(vo_hal_layer vo_layer, vo_int_mode int_mode)
{
hal_video_set_layer_up_mode(vo_layer, int_mode);
return;
}
gk_void vo_drv_set_dev_intf_type(gk_s32 vo_dev, vo_intf_type intf_type)
{
g_hal_dev_cfg[vo_dev].intf_type = intf_type;
return;
}
gk_void vo_drv_set_dev_bk_grd(gk_s32 vo_dev, gk_u32 bg_color)
{
g_hal_dev_cfg[vo_dev].bk_grd = bg_color;
return;
}
gk_void vo_drv_set_dev_out_sync(gk_s32 vo_dev, vo_intf_sync vo_out_mode)
{
g_hal_dev_cfg[vo_dev].out_sync = vo_out_mode;
return;
}
/* interrupt relative */
gk_void vo_drv_dev_int_enable(vo_hal_dev vo_dev, gk_bool enable)
{
vo_int_mask int_type;
switch (vo_dev) {
case VO_DEV_DHD0:
int_type = VO_INTMSK_DHD0_VTTHD1;
break;
default:
return;
}
if (enable == GK_TRUE) {
hal_disp_set_int_mask(int_type);
} else {
hal_disp_clr_int_mask(int_type);
}
return;
}
gk_void vo_drv_int_set_mode(gk_s32 vo_dev, vo_int_mode int_mode)
{
hal_disp_set_vt_thd_mode(vo_dev, int_mode);
return;
}
gk_void vo_drv_layer_enable(vo_hal_layer vo_layer, gk_bool enable)
{
hal_layer_enable_layer(vo_layer, enable);
return;
}
gk_void vo_drv_def_layer_bind_dev(gk_void)
{
hal_cbm_set_cbm_mixer_prio(HAL_DISP_LAYER_VHD0, VO_MIX_PRIO0, HAL_CBMMIX1);
hal_cbm_set_cbm_mixer_prio(HAL_DISP_LAYER_GFX0, VO_MIX_PRIO1, HAL_CBMMIX1);
return;
}
gk_void vo_drv_set_dev_clk(vo_hal_dev vo_dev)
{
/* the numbers below is the default value of the register. */
gk_bool clk_en = GK_FALSE;
gk_u32 vdp_out_clk_sel = 0x0;
gk_u32 vdp_hd_clk_sel = 0x0;
gk_u32 lcd_mclk_div = 0x00FFFFF;
switch (g_hal_dev_cfg[vo_dev].out_sync) {
/* the number is pll register config, calculate from out sync */
case VO_OUTPUT_PAL:
case VO_OUTPUT_NTSC:
case VO_OUTPUT_576P50:
case VO_OUTPUT_480P60: {
/* 27MHz */
vdp_out_clk_sel = 0xa;
break;
}
case VO_OUTPUT_1080P24:
case VO_OUTPUT_1080P25:
case VO_OUTPUT_1080P30:
case VO_OUTPUT_720P50:
case VO_OUTPUT_720P60:
case VO_OUTPUT_1080I50:
case VO_OUTPUT_1080I60:
case VO_OUTPUT_720x1280_60: {
/* 74.25MHz */
vdp_out_clk_sel = 0x8;
break;
}
case VO_OUTPUT_1080P50:
case VO_OUTPUT_1080P60:
case VO_OUTPUT_1920x2160_30:
case VO_OUTPUT_1080x1920_60: {
/* 148.5MHz */
vdp_out_clk_sel = 0x0;
break;
}
case VO_OUTPUT_640x480_60: {
/* 25.175MHz */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x1cac08;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_800x600_60: {
/* 40MHz */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x2d45b3;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_1024x768_60: {
/* 65MHz */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x49f369;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_1280x1024_60: {
/* 108MHz */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x7ad6ef;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_1366x768_60: {
/* 85.5MHz */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x619f57;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_1280x800_60: {
/* 83.5MHz */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x5f4e44;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_320x240_60: {
/* lcd clk config */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x3;
lcd_mclk_div = 0x1c4255;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_320x240_50: {
/* lcd clk config */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x2;
lcd_mclk_div = 0xdf346;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_240x320_50: {
/* lcd clk config */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x2;
lcd_mclk_div = 0xff5f3;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_240x320_60: {
/* lcd clk config */
vdp_out_clk_sel = 0x5;
vdp_hd_clk_sel = 0x0;
lcd_mclk_div = 0x5f8d2;
clk_en = GK_TRUE;
break;
}
case VO_OUTPUT_USER: {
if (vo_dev == 0) {
if (g_user_intfsync_info.user_intf_sync_attr.clk_source == VO_CLK_SOURCE_LCDMCLK) {
/* LCD_MCLK_DIV */
vdp_out_clk_sel = 0x5; /* 0x5 register value for lcd */
sys_hal_vo_out_clk_sel(vdp_out_clk_sel);
/* configuring the clock */
sys_hal_lcd_mclk_div(g_user_intfsync_info.user_intf_sync_attr.lcd_m_clk_div);
sys_hal_vo_lcd_clk_en(GK_TRUE);
} else if (g_user_intfsync_info.user_intf_sync_attr.clk_source == VO_CLK_SOURCE_PLL) {
printf("vo_dev(%d) clk source %d illegal.\n", vo_dev,
g_user_intfsync_info.user_intf_sync_attr.clk_source);
}
} else {
printf("VO dev %d is illegal\n", vo_dev);
}
sys_hal_vo_hd_out_pctrl(g_user_intfsync_info.clk_reverse);
sys_hal_vo_hd0_div_mode(g_user_intfsync_info.dev_div - 1);
if ((VO_INTF_LCD_6BIT & g_hal_dev_cfg[vo_dev].intf_type) ||
(VO_INTF_LCD_8BIT & g_hal_dev_cfg[vo_dev].intf_type)) {
if (g_user_intfsync_info.dev_div == 3) { /* div 3 */
hal_disp_set_lcd_serial_perd(0);
} else {
hal_disp_set_lcd_serial_perd(1);
}
}
return;
break;
}
default: {
return;
}
}
sys_hal_vo_lcd_clk_en(clk_en);
sys_hal_lcd_mclk_div(lcd_mclk_div);
sys_hal_vo_hd0_div_mode(vdp_hd_clk_sel);
sys_hal_vo_out_clk_sel(vdp_out_clk_sel);
return;
}
static gk_bool vo_drv_get_dither_io_mode(gk_u32 dither_io_mode,
gk_u32 *dither_mode,
gk_u32 *i_data_width_dither,
gk_u32 *o_data_width_dither)
{
if (dither_io_mode == DITHER_IO_MODE_12_10) {
*dither_mode = DITHER_MODE_10BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_12BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_10BIT;
} else if (dither_io_mode == DITHER_IO_MODE_12_8) {
*dither_mode = DITHER_MODE_8BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_12BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_8BIT;
} else if (dither_io_mode == DITHER_IO_MODE_10_8) {
*dither_mode = DITHER_MODE_8BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_10BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_8BIT;
} else if (dither_io_mode == DITHER_IO_MODE_10_6) {
*dither_mode = DITHER_MODE_8BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_10BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_6BIT;
} else if (dither_io_mode == DITHER_IO_MODE_9_6) {
*dither_mode = DITHER_MODE_8BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_9BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_6BIT;
} else if (dither_io_mode == DITHER_IO_MODE_8_6) {
*dither_mode = DITHER_MODE_8BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_8BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_6BIT;
} else if (dither_io_mode == 0) {
*dither_mode = DITHER_MODE_8BIT;
*i_data_width_dither = DITHER_IWIDTH_MODE_8BIT;
*o_data_width_dither = DITHER_OWIDTH_MODE_6BIT;
} else {
return GK_FALSE;
}
return GK_TRUE;
}
static gk_void vo_drv_get_dither_sed(hal_disp_dihter_sed *tmp_sed)
{
/* number is from algorithm, not magic number */
tmp_sed->dither_sed_y0 = 2147483647;
tmp_sed->dither_sed_u0 = 2147482647;
tmp_sed->dither_sed_v0 = 2147481647;
tmp_sed->dither_sed_w0 = 2147480647;
tmp_sed->dither_sed_y1 = tmp_sed->dither_sed_y0;
tmp_sed->dither_sed_u1 = tmp_sed->dither_sed_u0;
tmp_sed->dither_sed_v1 = tmp_sed->dither_sed_v0;
tmp_sed->dither_sed_w1 = tmp_sed->dither_sed_w0;
tmp_sed->dither_sed_y2 = tmp_sed->dither_sed_y0;
tmp_sed->dither_sed_u2 = tmp_sed->dither_sed_u0;
tmp_sed->dither_sed_v2 = tmp_sed->dither_sed_v0;
tmp_sed->dither_sed_w2 = tmp_sed->dither_sed_w0;
tmp_sed->dither_sed_y3 = tmp_sed->dither_sed_y0;
tmp_sed->dither_sed_u3 = tmp_sed->dither_sed_u0;
tmp_sed->dither_sed_v3 = tmp_sed->dither_sed_v0;
tmp_sed->dither_sed_w3 = tmp_sed->dither_sed_w0;
return;
}
gk_void vo_drv_set_dev_dither_mode(vo_hal_dev vo_dev, vdp_dither_mode drv_dither_mode, vdp_dither_cfg *cfg)
{
hal_disp_outputchannel vo_channel;
hal_disp_dihter_sed dither_sed;
gk_u32 dither_round_unlim;
gk_u32 i_data_width_dither = 0;
gk_u32 o_data_width_dither = 0;
gk_u32 dither_en;
gk_u32 dither_io_mode;
gk_u32 dither_mode = 0;
gk_u32 dither_round;
gk_u32 dither_domain_mode;
gk_u32 dither_tap_mode;
gk_u32 dither_thr_max = 0;
gk_u32 dither_thr_min = 0;
gk_bool ret = GK_FALSE;
dither_en = cfg->dither_en;
dither_round = cfg->dither_round;
dither_round_unlim = cfg->dither_round_unlim;
dither_domain_mode = cfg->dither_domain_mode;
dither_tap_mode = cfg->dither_tap_mode;
dither_io_mode = cfg->dither_io_mode;
ret = vo_drv_get_dither_io_mode(dither_io_mode, &dither_mode, &i_data_width_dither, &o_data_width_dither);
if (ret == GK_FALSE) {
return;
}
if (drv_dither_mode == VDP_DITHER_MODE_TYP) {
vo_drv_get_dither_sed(&dither_sed);
dither_thr_max = 60000; /* 60000 max */
dither_thr_min = 120; /* 120 min */
} else {
return;
}
vo_channel = HAL_DISP_CHANNEL_DHD0;
hal_disp_set_dither_round_unlim(vo_channel, dither_round_unlim);
hal_disp_set_dither_data_in_out(vo_channel, i_data_width_dither, o_data_width_dither);
hal_disp_set_dither_en(vo_channel, dither_en);
hal_disp_set_dither_mode(vo_channel, dither_mode);
hal_disp_set_dither_round(vo_channel, dither_round);
hal_disp_set_dither_domain_mode(vo_channel, dither_domain_mode);
hal_disp_set_dither_tap_mode(vo_channel, dither_tap_mode);
hal_disp_set_dither_sed(vo_channel, &dither_sed);
hal_disp_set_dither_thr_min_max(vo_channel, dither_thr_min, dither_thr_max);
}
gk_void vo_drv_set_dev_dither_cfg(vo_hal_dev vo_dev, gk_u32 in_bit_widht, gk_u32 out_bit_widht)
{
vdp_dither_cfg dither_cfg;
if ((in_bit_widht == 10) && (out_bit_widht == 8)) { /* 10bit 8bit */
/* the numbers below are register config, not magic number. */
dither_cfg.dither_en = 1;
dither_cfg.dither_round = 1;
dither_cfg.dither_round_unlim = 1;
dither_cfg.dither_domain_mode = 1;
dither_cfg.dither_tap_mode = 1;
dither_cfg.dither_io_mode = DITHER_IO_MODE_12_8;
vo_drv_set_dev_dither_mode(vo_dev, VDP_DITHER_MODE_TYP, &dither_cfg);
hal_disp_set_dither_en(vo_dev, GK_TRUE);
hal_disp_set_dither_data_in_out(vo_dev, 0x4, 0x5); /* 4:12bit 5:10bit;3:8bit */
} else if ((in_bit_widht == 10) && (out_bit_widht == 6)) { /* 10bit 6bit */
/* the numbers below are register config, not magic number. */
dither_cfg.dither_en = 1;
dither_cfg.dither_round = 0;
dither_cfg.dither_round_unlim = 1;
dither_cfg.dither_domain_mode = 1;
dither_cfg.dither_tap_mode = 1;
dither_cfg.dither_io_mode = DITHER_IO_MODE_10_6;
vo_drv_set_dev_dither_mode(vo_dev, VDP_DITHER_MODE_TYP, &dither_cfg);
hal_disp_set_dither_en(vo_dev, GK_TRUE);
hal_disp_set_dither_data_in_out(vo_dev, 0x2, 0x1); /* 4:12bit 5:10bit;3:8bit */
} else if (((in_bit_widht == 10) && (out_bit_widht == 10)) || /* 10bit */
((in_bit_widht == 8) && (out_bit_widht == 8))) { /* 8bit */
hal_disp_set_dither_en(vo_dev, GK_FALSE);
}
}
gk_u32 vo_drv_get_dev_vtth(vo_hal_dev vo_dev)
{
gk_u32 dev_vtth;
switch (g_hal_dev_cfg[vo_dev].out_sync) {
case VO_OUTPUT_3840x2160_60:
case VO_OUTPUT_3840x2160_50:
case VO_OUTPUT_4096x2160_60:
case VO_OUTPUT_4096x2160_50:
dev_vtth = 4 * VO_HD_VTTH_WATERLINE; /* 4 times of default */
break;
case VO_OUTPUT_2560x1600_60:
case VO_OUTPUT_3840x2160_24:
case VO_OUTPUT_3840x2160_25:
case VO_OUTPUT_3840x2160_30:
case VO_OUTPUT_4096x2160_24:
case VO_OUTPUT_4096x2160_25:
case VO_OUTPUT_4096x2160_30:
dev_vtth = 2 * VO_HD_VTTH_WATERLINE; /* 2 times of default */
break;
default:
dev_vtth = VO_HD_VTTH_WATERLINE;
}
return dev_vtth;
}
/* turn on clk */
gk_void vo_drv_set_all_crg_clk(gk_bool clk_en)
{
gk_bool vo_clk_en = clk_en;
sys_hal_vo_dev_clk_en(0, vo_clk_en); /* dev 0 */
sys_hal_vo_core_clk_en(0, vo_clk_en); /* dev 0 */
sys_hal_vo_cfg_clk_en(vo_clk_en);
sys_hal_vo_apb_clk_en(vo_clk_en);
sys_hal_vo_bus_clk_en(vo_clk_en);
return;
}
gk_u32 vo_drv_get_dev_intf_type(vo_hal_dev vo_dev)
{
return g_hal_dev_cfg[vo_dev].intf_type;
}
void vo_drv_set_cbm_bkg(gk_s32 vo_dev)
{
hal_disp_bkcolor bkg;
vo_intf_type intf_type;
gk_u32 yuv_bk_grd = 0;
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
intf_type = hal_dev_cfg->intf_type;
if ((VO_INTF_LCD_6BIT & intf_type) ||
(VO_INTF_LCD_8BIT & intf_type) ||
(VO_INTF_LCD_16BIT & intf_type)) {
bkg.bkg_y = rgb_r(hal_dev_cfg->bk_grd);
bkg.bkg_cb = rgb_g(hal_dev_cfg->bk_grd);
bkg.bkg_cr = rgb_b(hal_dev_cfg->bk_grd);
/* for 30bit register. */
bkg.bkg_y = bkg.bkg_y << 2; /* 2 to turn 8 to 10 value */
bkg.bkg_cb = bkg.bkg_cb << 2; /* 2 to turn 8 to 10 value */
bkg.bkg_cr = bkg.bkg_cr << 2; /* 2 to turn 8 to 10 value */
} else {
yuv_bk_grd = rgb_to_yuv_full(hal_dev_cfg->bk_grd);
bkg.bkg_y = yuv_y(yuv_bk_grd);
bkg.bkg_cb = yuv_u(yuv_bk_grd);
bkg.bkg_cr = yuv_v(yuv_bk_grd);
}
hal_cbm_set_cbm_bkg(HAL_CBMMIX1, &bkg);
}
void vo_drv_get_intf_property(gk_s32 vo_dev, hal_disp_syncinfo *sync_info, hal_disp_syncinv *inv)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
if (hal_dev_cfg->out_sync != VO_OUTPUT_USER) {
memcpy(sync_info, &g_sync_timing[hal_dev_cfg->out_sync], sizeof(hal_disp_syncinfo));
} else {
memcpy(sync_info, &g_user_sync_timing, sizeof(hal_disp_syncinfo));
}
/* the numbers below are register config, not magic number. */
inv->hs_inv = sync_info->ihs ? 1 : 0;
inv->vs_inv = sync_info->ivs ? 1 : 0;
inv->dv_inv = sync_info->idv ? 1 : 0;
}
void vo_drv_set_intf_bt1120_cfg(gk_s32 vo_dev, hal_disp_syncinfo *sync_info, hal_disp_syncinv *inv)
{
sys_hal_vo_bt_clk_en(GK_TRUE);
hal_disp_set_intf_mux_sel(vo_dev, VO_INTF_BT1120);
hal_intf_bt_set_dfir_en(0x1); /* 0x1 enable */
}
void vo_drv_set_intf_bt656_cfg(gk_s32 vo_dev, hal_disp_syncinfo *sync_info, hal_disp_syncinv *inv, gk_u32 *div_mod)
{
sys_hal_vo_bt_clk_en(GK_TRUE);
/* the numbers below are register config, not magic number. */
hal_disp_set_intf_mux_sel(vo_dev, VO_INTF_BT656);
hal_intf_bt_set_dfir_en(0x1);
*div_mod = 1;
}
void vo_drv_set_intf_lcd_cfg(gk_s32 vo_dev, hal_disp_syncinfo *sync_info, hal_disp_syncinv *inv, gk_u32 *div_mod)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
U_INTF_LCD_CTRL LCD_CTRL;
vo_intf_type intf_type;
gk_u32 data_mode = 0x0;
vo_intf_sync out_sync;
intf_type = hal_dev_cfg->intf_type;
out_sync = hal_dev_cfg->out_sync;
sys_hal_vo_bt_clk_en(GK_TRUE);
sys_hal_vo_lcd_clk_en(GK_TRUE);
hal_disp_set_intf_mux_sel(vo_dev, intf_type);
if (VO_INTF_LCD_8BIT & intf_type) {
/* the numbers below are register config, not magic number. */
*div_mod = 3; /* 3 register config */
data_mode = 1;
LCD_CTRL.bits.hdmi_mode = 1;
LCD_CTRL.bits.lcd_serial_mode = 1;
LCD_CTRL.bits.lcd_serial_perd = 1;
LCD_CTRL.bits.lcd_parallel_order = 0;
LCD_CTRL.bits.lcd_data_inv = 0;
LCD_CTRL.bits.lcd_parallel_mode = 1; /* 0:RGB565, 1:RGB888 */
} else if (VO_INTF_LCD_6BIT & intf_type) {
/* the numbers below are register config, not magic number. */
*div_mod = 2; /* 2 register config */
data_mode = 0;
LCD_CTRL.bits.lcd_serial_mode = 1;
LCD_CTRL.bits.lcd_serial_perd = 0;
LCD_CTRL.bits.lcd_parallel_order = 0;
LCD_CTRL.bits.lcd_data_inv = 0;
LCD_CTRL.bits.lcd_parallel_mode = 0;
} else if (VO_INTF_LCD_16BIT & intf_type) {
/* the numbers below are register config, not magic number. */
*div_mod = 0;
data_mode = 2; /* 2 register config */
LCD_CTRL.bits.lcd_serial_mode = 0;
LCD_CTRL.bits.lcd_serial_perd = 0;
LCD_CTRL.bits.lcd_parallel_order = 0;
LCD_CTRL.bits.lcd_data_inv = 0;
LCD_CTRL.bits.lcd_parallel_mode = 1;
}
sys_hal_lcd_data_mode(data_mode);
hal_disp_set_intf_ctrl(intf_type, &(LCD_CTRL.u32));
if (out_sync != VO_OUTPUT_USER) {
hal_disp_set_lcd_serial_perd(LCD_CTRL.bits.lcd_serial_perd);
}
}
void vo_drv_set_intf_cfg(gk_s32 vo_dev, hal_disp_syncinfo *sync_info, hal_disp_syncinv *inv, gk_u32 *div_mod)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
vo_intf_type intf_type;
intf_type = hal_dev_cfg->intf_type;
if (VO_INTF_BT1120 & hal_dev_cfg->intf_type) {
vo_drv_set_intf_bt1120_cfg(vo_dev, sync_info, inv);
}
if (VO_INTF_BT656 & intf_type) {
vo_drv_set_intf_bt656_cfg(vo_dev, sync_info, inv, div_mod);
}
if ((VO_INTF_LCD_6BIT & intf_type) ||
(VO_INTF_LCD_8BIT & intf_type) ||
(VO_INTF_LCD_16BIT & intf_type)) {
vo_drv_set_intf_lcd_cfg(vo_dev, sync_info, inv, div_mod);
}
}
void vo_drv_set_dev_multichn(gk_s32 vo_dev)
{
hal_multi_chn multi_chn_en = HAL_MULTICHN_EN_1P1C;
hal_disp_set_dev_multi_chn_en(vo_dev, multi_chn_en);
}
void vo_drv_set_dev_clip_by_intf(gk_s32 vo_dev)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
vo_intf_type intf_type;
intf_type = hal_dev_cfg->intf_type;
if (VO_INTF_BT1120 & intf_type) {
const hal_disp_clip clip_data = { 0x40, 0x40, 0x40, 0x3ac, 0x3c0, 0x3c0 }; /* clip register config */
hal_disp_set_intf_clip(VO_INTF_BT1120, GK_TRUE, &clip_data);
}
if (VO_INTF_BT656 & intf_type) {
const hal_disp_clip clip_data = { 0x40, 0x40, 0x40, 0x3ac, 0x3c0, 0x3c0 }; /* clip register config */
hal_disp_set_intf_clip(VO_INTF_BT656, GK_TRUE, &clip_data);
}
}
void vo_drv_set_dev_int_mode(gk_s32 vo_dev, hal_disp_syncinfo *sync_info)
{
vo_int_mode int_mode;
if (sync_info->iop == 0) {
int_mode = VO_INT_MODE_FIELD;
} else {
int_mode = VO_INT_MODE_FRAME;
}
vo_drv_int_set_mode(vo_dev, int_mode);
vo_drv_int_reg_up_mode(vo_dev, int_mode);
}
void vo_drv_set_dev_out_pctrl(gk_s32 vo_dev)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
vo_intf_sync out_sync;
gk_bool clk_reverse = GK_TRUE;
out_sync = hal_dev_cfg->out_sync;
if (out_sync != VO_OUTPUT_USER) {
sys_hal_vo_hd_out_pctrl(clk_reverse);
}
}
void vo_drv_set_dev_div_mod(gk_s32 vo_dev, gk_u32 div_mod)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
vo_intf_sync out_sync;
out_sync = hal_dev_cfg->out_sync;
if (out_sync != VO_OUTPUT_USER) {
if (vo_dev == 0) {
sys_hal_vo_hd0_div_mode(div_mod);
}
}
}
void vo_drv_set_dev_dither(gk_s32 vo_dev)
{
hal_dev_config *hal_dev_cfg = &g_hal_dev_cfg[vo_dev];
vo_intf_type intf_type;
intf_type = hal_dev_cfg->intf_type;
if ((VO_INTF_LCD_6BIT & intf_type) ||
(VO_INTF_LCD_16BIT & intf_type)) {
vo_drv_set_dev_dither_cfg(vo_dev, 10, 6); /* 10 to 6 */
} else {
vo_drv_set_dev_dither_cfg(vo_dev, 10, 8); /* 10 to 8 */
}
}
gk_void vo_drv_open(gk_s32 vo_dev)
{
hal_disp_syncinfo sync_info;
gk_u16 vtth_line;
hal_disp_syncinv inv = {0};
gk_u32 div_mode = 0;
vo_drv_set_all_crg_clk(GK_TRUE);
hal_disp_set_intf_enable(vo_dev, GK_FALSE);
sys_hal_vo_dev_clk_en(0, GK_TRUE);
sys_hal_vo_out_clk_en(0, GK_TRUE);
vo_drv_set_cbm_bkg(vo_dev);
/* set interface property */
vo_drv_get_intf_property(vo_dev, &sync_info, &inv);
vo_drv_set_intf_cfg(vo_dev, &sync_info, &inv, &div_mode);
vo_drv_set_dev_out_pctrl(vo_dev);
vo_drv_set_dev_div_mod(vo_dev, div_mode);
hal_disp_set_intf_sync(vo_dev, &sync_info, &inv);
vo_drv_set_dev_multichn(vo_dev);
/* set clip */
vo_drv_set_dev_clip_by_intf(vo_dev);
vo_drv_set_dev_int_mode(vo_dev, &sync_info);
vtth_line = sync_info.vact + sync_info.vfb + sync_info.vbb - 1 - vo_drv_get_dev_vtth(vo_dev);
hal_disp_set_vt_thd(vo_dev, vtth_line);
/* dither config */
vo_drv_set_dev_dither(vo_dev);
hal_disp_set_intf_enable(vo_dev, GK_TRUE);
vo_drv_dev_int_enable(vo_dev, GK_TRUE);
hal_disp_set_reg_up(vo_dev);
g_hal_dev_cfg[vo_dev].enable = GK_TRUE;
return;
}
gk_void vo_drv_close(gk_s32 vo_dev)
{
gk_u32 i;
hal_disp_set_intf_enable(vo_dev, GK_FALSE);
hal_disp_set_reg_up(vo_dev);
hal_disp_set_intf_mux_sel(vo_dev, HAL_DISP_INTF_BUTT);
g_hal_dev_cfg[vo_dev].enable = GK_FALSE;
for (i = 0; i < VO_DEV_MAX_NUM; i++) {
if (g_hal_dev_cfg[vo_dev].enable) {
break;
}
}
if (i == VO_DEV_MAX_NUM) {
vo_drv_set_all_crg_clk(GK_FALSE);
}
return;
}
gk_void vo_drv_default_setting(gk_void)
{
hal_layer_set_layer_galpha(HAL_DISP_LAYER_VHD0, 255); /* 255 max alpha */
vo_drv_layer_enable(HAL_DISP_LAYER_VHD0, GK_FALSE);
return;
}
gk_void vo_drv_func_get_cvfir_pq_cfg(vo_zme_ds_info *ds_info, vo_zme_mode zme_mode,
vo_zme_comm_pq_cfg *comm_pq_cfg)
{
gk_u32 zme_vprec;
/* the zme num is from algorithm, not magic num */
if (zme_mode == VO_ZME_TYP) {
zme_vprec = ds_info->zme_vprec;
comm_pq_cfg->vluma_offset = 0;
comm_pq_cfg->vchroma_offset = 0;
comm_pq_cfg->vbluma_offset = MIN_OFFSET * (gk_s32)zme_vprec / 2;
comm_pq_cfg->vbchroma_offset = MIN_OFFSET * (gk_s32)zme_vprec / 2;
comm_pq_cfg->vl_flatdect_mode = 1;
comm_pq_cfg->vl_coringadj_en = 1;
comm_pq_cfg->vl_gain = 32;
comm_pq_cfg->vl_coring = 16;
comm_pq_cfg->vc_flatdect_mode = 1;
comm_pq_cfg->vc_coringadj_en = 1;
comm_pq_cfg->vc_gain = 32;
comm_pq_cfg->vc_coring = 16;
comm_pq_cfg->lhfir_offset = 0;
comm_pq_cfg->chfir_offset = 0;
comm_pq_cfg->hl_flatdect_mode = 1;
comm_pq_cfg->hl_coringadj_en = 1;
comm_pq_cfg->hl_gain = 32;
comm_pq_cfg->hl_coring = 16;
comm_pq_cfg->hc_flatdect_mode = 1;
comm_pq_cfg->hc_coringadj_en = 1;
comm_pq_cfg->hc_gain = 32;
comm_pq_cfg->hc_coring = 16;
}
}
static gk_void vo_drv_set_layer_cvfir_mode(gk_u32 layer, vo_zme_mode zme_mode, const vdp_v1_cvfir_cfg *cfg)
{
gk_u32 vzme_ck_gt_en;
gk_u32 out_pro;
gk_u32 out_fmt;
gk_u32 out_height;
gk_u32 cvfir_en;
gk_u32 cvmid_en;
gk_u32 cvfir_mode;
gk_u32 vratio;
gk_u32 vchroma_offset;
gk_u32 vbchroma_offset;
vo_zme_ds_info ds_info = {0};
vo_zme_comm_pq_cfg comm_pq_cfg = {0};
ds_info.zme_vprec = ZME_VPREC;
ds_info.zme_hprec = ZME_HPREC;
vzme_ck_gt_en = cfg->ck_gt_en;
cvfir_en = cfg->cvfir_en;
cvfir_mode = cfg->cvfir_mode;
cvmid_en = cfg->cvmid_en;
out_pro = cfg->out_pro;
out_fmt = cfg->out_fmt;
out_height = cfg->in_height;
vratio = ds_info.zme_vprec;
vo_drv_func_get_cvfir_pq_cfg(&ds_info, zme_mode, &comm_pq_cfg);
vchroma_offset = comm_pq_cfg.vchroma_offset;
vbchroma_offset = comm_pq_cfg.vbchroma_offset;
hal_video_cvfir_set_out_height(layer, out_height);
hal_video_cvfir_set_out_fmt(layer, out_fmt);
hal_video_cvfir_set_out_pro(layer, out_pro);
hal_video_cvfir_set_vzme_ck_gt_en(layer, vzme_ck_gt_en);
hal_video_cvfir_set_cvfir_en(layer, cvfir_en);
hal_video_cvfir_set_cvmid_en(layer, cvmid_en);
hal_video_cvfir_set_cvfir_mode(layer, cvfir_mode);
hal_video_cvfir_set_vratio(layer, vratio);
hal_video_cvfir_set_v_chroma_offset(layer, vchroma_offset);
hal_video_cvfir_set_vb_chroma_offset(layer, vbchroma_offset);
}
gk_void vo_vid_set_zme_enable(gk_u32 layer, const vdp_vid_ip_cfg *vid_cfg)
{
/* the numbers below are register config from algorithm, not magic number. */
vdp_v1_cvfir_cfg cvfir_cfg;
cvfir_cfg.hfir_order = 0;
cvfir_cfg.lhfir_en = 0;
cvfir_cfg.chfir_en = 0;
cvfir_cfg.lhmid_en = 0;
cvfir_cfg.chmid_en = 0;
cvfir_cfg.lhfir_mode = 0;
cvfir_cfg.chfir_mode = 0;
cvfir_cfg.hl_shootctrl_en = 0;
cvfir_cfg.hl_shootctrl_mode = 0;
cvfir_cfg.hc_shootctrl_en = 0;
cvfir_cfg.hc_shootctrl_mode = 0;
cvfir_cfg.lvfir_en = 0;
cvfir_cfg.lvmid_en = 0;
cvfir_cfg.lvfir_mode = 0;
cvfir_cfg.vl_shootctrl_en = 0;
cvfir_cfg.vl_shootctrl_mode = 0;
cvfir_cfg.vc_shootctrl_en = 0;
cvfir_cfg.vc_shootctrl_mode = 0;
/* CVFIR */
cvfir_cfg.ck_gt_en = 0;
cvfir_cfg.cvfir_en = 1;
cvfir_cfg.cvmid_en = 0;
cvfir_cfg.cvfir_mode = 0;
cvfir_cfg.out_pro = VDP_RMODE_PROGRESSIVE;
cvfir_cfg.out_fmt = VDP_PROC_FMT_SP_422;
cvfir_cfg.in_width = vid_cfg->vid_iw;
cvfir_cfg.in_height = vid_cfg->vid_ih;
cvfir_cfg.out_width = vid_cfg->vid_ow;
cvfir_cfg.out_height = vid_cfg->vid_oh;
vo_drv_set_layer_cvfir_mode(layer, VO_ZME_TYP, &cvfir_cfg);
}
gk_s32 vo_drv_get_csc_matrix(hal_csc_mode csc_mode, const vo_csc_coef **csc_tmp)
{
switch (csc_mode) {
case HAL_CSC_MODE_BT601_TO_BT601:
case HAL_CSC_MODE_BT709_TO_BT709:
case HAL_CSC_MODE_RGB_TO_RGB:
*csc_tmp = &g_csc_init;
break;
case HAL_CSC_MODE_BT709_TO_BT601:
*csc_tmp = &g_csc_yuv_to_yuv_709_601;
break;
case HAL_CSC_MODE_BT601_TO_BT709:
*csc_tmp = &g_csc_yuv_to_yuv_601_709;
break;
case HAL_CSC_MODE_BT601_TO_RGB_PC:
*csc_tmp = &g_csc_yuv601_to_rgb_pc;
break;
case HAL_CSC_MODE_BT709_TO_RGB_PC:
*csc_tmp = &g_csc_yuv709_to_rgb_pc;
break;
case HAL_CSC_MODE_RGB_TO_BT601_PC:
*csc_tmp = &g_csc_rgb_to_yuv601_pc;
break;
case HAL_CSC_MODE_RGB_TO_BT709_PC:
*csc_tmp = &g_csc_rgb_to_yuv709_pc;
break;
case HAL_CSC_MODE_RGB_TO_BT601_TV:
*csc_tmp = &g_csc_rgb_to_yuv601_tv;
break;
case HAL_CSC_MODE_RGB_TO_BT709_TV:
*csc_tmp = &g_csc_rgb_to_yuv709_tv;
break;
default:
return GK_FAILURE;
}
return GK_SUCCESS;
}
gk_void vo_drv_get_hal_cscvalue(const vo_csc *csc, hal_csc_value *csc_value)
{
csc_value->luma = (gk_s32)csc->luma * 64 / 100 - 32; /* x64/100 -32 to adjust the value */
csc_value->cont = ((gk_s32)csc->contrast - 50) * 2 + 100; /* -50) * 2 + 100 to adjust the value */
csc_value->hue = (gk_s32)csc->hue * 60 / 100; /* x60/100 to adjust the value */
csc_value->satu = ((gk_s32)csc->satuature - 50) * 2 + 100; /* -50) * 2 + 100 to adjust the value */
}
gk_void vo_drv_set_csc_coef_y2r(const hal_csc_value *csc_value, const vo_csc_coef *csc_tmp, vo_csc_coef *csc_coef)
{
gk_s32 luma;
gk_s32 contrast;
gk_s32 hue;
gk_s32 satu;
luma = csc_value->luma;
contrast = csc_value->cont;
hue = csc_value->hue;
satu = csc_value->satu;
/* 100 and 1000 is to adjust the coef */
csc_coef->csc_coef00 = (contrast * csc_tmp->csc_coef00) / 100;
csc_coef->csc_coef01 = (contrast * satu * ((csc_tmp->csc_coef01 * g_cos_table[hue] -
csc_tmp->csc_coef02 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef02 = (contrast * satu * ((csc_tmp->csc_coef01 * g_sin_table[hue] +
csc_tmp->csc_coef02 * g_cos_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef10 = (contrast * csc_tmp->csc_coef10) / 100;
csc_coef->csc_coef11 = (contrast * satu * ((csc_tmp->csc_coef11 * g_cos_table[hue] -
csc_tmp->csc_coef12 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef12 = (contrast * satu * ((csc_tmp->csc_coef11 * g_sin_table[hue] +
csc_tmp->csc_coef12 * g_cos_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef20 = (contrast * csc_tmp->csc_coef20) / 100;
csc_coef->csc_coef21 = (contrast * satu * ((csc_tmp->csc_coef21 * g_cos_table[hue] -
csc_tmp->csc_coef22 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef22 = (contrast * satu * ((csc_tmp->csc_coef21 * g_sin_table[hue] +
csc_tmp->csc_coef22 * g_cos_table[hue]) / 1000)) / 10000;
csc_coef->csc_in_dc0 += (contrast != 0) ? (luma * 100 / contrast) : luma * 100;
}
gk_void vo_drv_set_csc_coef_r2y(hal_csc_value *csc_value, const vo_csc_coef *csc_tmp, vo_csc_coef *csc_coef)
{
gk_s32 luma;
gk_s32 contrast;
gk_s32 hue;
gk_s32 satu;
luma = csc_value->luma;
contrast = csc_value->cont;
hue = csc_value->hue;
satu = csc_value->satu;
/* 100 and 1000 is to adjust the coef */
csc_coef->csc_coef00 = (contrast * csc_tmp->csc_coef00) / 100;
csc_coef->csc_coef01 = (contrast * csc_tmp->csc_coef01) / 100;
csc_coef->csc_coef02 = (contrast * csc_tmp->csc_coef02) / 100;
csc_coef->csc_coef10 = (contrast * satu * ((csc_tmp->csc_coef10 * g_cos_table[hue] +
csc_tmp->csc_coef20 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef11 = (contrast * satu * ((csc_tmp->csc_coef11 * g_cos_table[hue] +
csc_tmp->csc_coef21 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef12 = (contrast * satu * ((csc_tmp->csc_coef12 * g_cos_table[hue] +
csc_tmp->csc_coef22 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef20 = (contrast * satu * ((csc_tmp->csc_coef20 * g_cos_table[hue] -
csc_tmp->csc_coef10 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef21 = (contrast * satu * ((csc_tmp->csc_coef21 * g_cos_table[hue] -
csc_tmp->csc_coef11 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_coef22 = (contrast * satu * ((csc_tmp->csc_coef22 * g_cos_table[hue] -
csc_tmp->csc_coef12 * g_sin_table[hue]) / 1000)) / 10000;
csc_coef->csc_out_dc0 += luma;
}
gk_void vo_drv_calc_csc_matrix(const vo_csc *csc, hal_csc_mode csc_mode, vo_csc_coef *cst_coef)
{
const vo_csc_coef *csc_tmp = GK_NULL;
gk_s32 ret;
hal_csc_value csc_value = {0};
vo_drv_get_hal_cscvalue(csc, &csc_value);
ret = vo_drv_get_csc_matrix(csc_mode, &csc_tmp);
if (ret != GK_SUCCESS) {
return;
}
cst_coef->csc_in_dc0 = csc_tmp->csc_in_dc0;
cst_coef->csc_in_dc1 = csc_tmp->csc_in_dc1;
cst_coef->csc_in_dc2 = csc_tmp->csc_in_dc2;
cst_coef->csc_out_dc0 = csc_tmp->csc_out_dc0;
cst_coef->csc_out_dc1 = csc_tmp->csc_out_dc1;
cst_coef->csc_out_dc2 = csc_tmp->csc_out_dc2;
if ((csc_mode == HAL_CSC_MODE_BT601_TO_RGB_PC) || (csc_mode == HAL_CSC_MODE_BT709_TO_RGB_PC) ||
(csc_mode == HAL_CSC_MODE_BT601_TO_RGB_TV) || (csc_mode == HAL_CSC_MODE_BT709_TO_RGB_TV)) {
vo_drv_set_csc_coef_y2r(&csc_value, csc_tmp, cst_coef);
} else {
vo_drv_set_csc_coef_r2y(&csc_value, csc_tmp, cst_coef);
}
return;
}
gk_s32 graphic_drv_set_csc_coef(hal_disp_layer gfx_layer, const vo_csc *gfx_csc, const csc_coef_param *coef_param)
{
vo_csc_coef coef;
hal_csc_mode csc_mode;
if (gfx_csc->csc_matrix == VO_CSC_MATRIX_IDENTITY) {
csc_mode = HAL_CSC_MODE_NONE;
} else if (gfx_csc->csc_matrix == VO_CSC_MATRIX_RGB_TO_BT601_PC) {
csc_mode = HAL_CSC_MODE_RGB_TO_BT601_PC;
} else if (gfx_csc->csc_matrix == VO_CSC_MATRIX_RGB_TO_BT709_PC) {
csc_mode = HAL_CSC_MODE_RGB_TO_BT709_PC;
} else {
printf("csc_matrix %d err, should only be RGB to yuv matrix\n", gfx_csc->csc_matrix);
return GK_FAILURE;
}
coef.new_csc_clip_max = GFX_CSC_CLIP_MAX;
coef.new_csc_clip_min = GFX_CSC_CLIP_MIN;
coef.new_csc_scale2p = GFX_CSC_SCALE;
hal_layer_set_csc_coef(gfx_layer, &coef);
hal_layer_csc_set_csc_mode(gfx_layer, csc_mode);
return GK_SUCCESS;
}
gk_void vo_drv_get_hal_cscmode(vo_csc_matrix csc_matrix, hal_csc_mode *csc_mode)
{
switch (csc_matrix) {
case VO_CSC_MATRIX_IDENTITY:
*csc_mode = HAL_CSC_MODE_BT601_TO_BT601;
break;
case VO_CSC_MATRIX_BT601_TO_BT709:
*csc_mode = HAL_CSC_MODE_BT601_TO_BT709;
break;
case VO_CSC_MATRIX_BT709_TO_BT601:
*csc_mode = HAL_CSC_MODE_BT709_TO_BT601;
break;
case VO_CSC_MATRIX_BT601_TO_RGB_PC:
*csc_mode = HAL_CSC_MODE_BT601_TO_RGB_PC;
break;
case VO_CSC_MATRIX_BT709_TO_RGB_PC:
*csc_mode = HAL_CSC_MODE_BT709_TO_RGB_PC;
break;
case VO_CSC_MATRIX_RGB_TO_BT601_PC:
*csc_mode = HAL_CSC_MODE_RGB_TO_BT601_PC;
break;
case VO_CSC_MATRIX_RGB_TO_BT709_PC:
*csc_mode = HAL_CSC_MODE_RGB_TO_BT709_PC;
break;
default:
*csc_mode = HAL_CSC_MODE_BT601_TO_BT601;
break;
}
}
gk_s32 vo_drv_video_set_csc_coef(vo_hal_layer vo_layer, vo_csc_matrix csc_matrix)
{
vo_csc_coef csc_coef;
hal_csc_mode csc_mode;
const gk_u32 dc_pre = 4;
vo_csc csc = {0};
/* 50 default value */
csc.contrast = 50;
csc.hue = 50;
csc.luma = 50;
csc.satuature = 50;
if ((vo_layer < LAYER_VHD_START) || (vo_layer > LAYER_VHD_END)) {
printf("[%s][%d] vo_layer:%d not supported\n", __FUNCTION__, __LINE__, vo_layer);
return GK_FAILURE;
}
vo_drv_get_hal_cscmode(csc_matrix, &csc_mode);
vo_drv_calc_csc_matrix(&csc, csc_mode, &csc_coef);
/* 0xfff 0x0 0x8 default value from algorithm */
csc_coef.new_csc_clip_max = 0xfff;
csc_coef.new_csc_clip_min = 0x0;
csc_coef.new_csc_scale2p = 0x8;
/* x1024/1000 is to adjust coef value */
csc_coef.csc_coef00 = csc_coef.csc_coef00 * 1024 / 1000;
csc_coef.csc_coef01 = csc_coef.csc_coef01 * 1024 / 1000;
csc_coef.csc_coef02 = csc_coef.csc_coef02 * 1024 / 1000;
csc_coef.csc_coef10 = csc_coef.csc_coef10 * 1024 / 1000;
csc_coef.csc_coef11 = csc_coef.csc_coef11 * 1024 / 1000;
csc_coef.csc_coef12 = csc_coef.csc_coef12 * 1024 / 1000;
csc_coef.csc_coef20 = csc_coef.csc_coef20 * 1024 / 1000;
csc_coef.csc_coef21 = csc_coef.csc_coef21 * 1024 / 1000;
csc_coef.csc_coef22 = csc_coef.csc_coef22 * 1024 / 1000;
/* 0x7ff is the max value */
csc_coef.csc_coef00 = (csc_coef.csc_coef00 > 0x7ff) ? 0x7ff : csc_coef.csc_coef00;
csc_coef.csc_coef01 = (csc_coef.csc_coef01 > 0x7ff) ? 0x7ff : csc_coef.csc_coef01;
csc_coef.csc_coef02 = (csc_coef.csc_coef02 > 0x7ff) ? 0x7ff : csc_coef.csc_coef02;
csc_coef.csc_coef10 = (csc_coef.csc_coef10 > 0x7ff) ? 0x7ff : csc_coef.csc_coef10;
csc_coef.csc_coef11 = (csc_coef.csc_coef11 > 0x7ff) ? 0x7ff : csc_coef.csc_coef11;
csc_coef.csc_coef12 = (csc_coef.csc_coef12 > 0x7ff) ? 0x7ff : csc_coef.csc_coef12;
csc_coef.csc_coef20 = (csc_coef.csc_coef20 > 0x7ff) ? 0x7ff : csc_coef.csc_coef20;
csc_coef.csc_coef21 = (csc_coef.csc_coef21 > 0x7ff) ? 0x7ff : csc_coef.csc_coef21;
csc_coef.csc_coef22 = (csc_coef.csc_coef22 > 0x7ff) ? 0x7ff : csc_coef.csc_coef22;
csc_coef.csc_in_dc0 = (gk_s32)csc_coef.csc_in_dc0;
csc_coef.csc_in_dc1 = (gk_s32)csc_coef.csc_in_dc1;
csc_coef.csc_in_dc2 = (gk_s32)csc_coef.csc_in_dc2;
csc_coef.csc_out_dc0 = (gk_s32)dc_pre * csc_coef.csc_out_dc0;
csc_coef.csc_out_dc1 = (gk_s32)dc_pre * csc_coef.csc_out_dc1;
csc_coef.csc_out_dc2 = (gk_s32)dc_pre * csc_coef.csc_out_dc2;
hal_layer_set_csc_coef(vo_layer, &csc_coef);
return GK_SUCCESS;
}
gk_s32 load_bmp(gk_phys_addr_t bmp_addr, osd_logo_t *video_logo)
{
gk_u16 bpp;
osd_bitmap_file_header bmp_file_header;
osd_bitmap_info bmp_info;
memcpy(&bmp_file_header, (char *)(uintptr_t)(bmp_addr + sizeof(gk_u16)), sizeof(osd_bitmap_file_header));
memcpy(&bmp_info, (char *)(uintptr_t)(bmp_addr + sizeof(gk_u16) + sizeof(osd_bitmap_file_header)), sizeof(osd_bitmap_info));
video_logo->width = bmp_info.bmi_header.bi_width;
video_logo->height = bmp_info.bmi_header.bi_height;
video_logo->stride = bmp_info.bmi_header.bi_width * (OSD_BI_BIT_COUNT_16BPP / 8); /* 8 bits per bytes */
video_logo->rgb_buffer = bmp_addr + bmp_file_header.bf_off_bits;
bpp = bmp_info.bmi_header.bi_bit_count;
if (bpp != OSD_BI_BIT_COUNT_16BPP) { /* 16 bits, 2bytes per pixel bitmap format */
printf("bitmap format bpp=%d not supported! only supoort format bpp=%d\n", bpp, OSD_BI_BIT_COUNT_16BPP);
return -1;
}
return 0;
}