blob: 76a0dfac901f54dbf3dfeba5e3df9e99a6858996 [file] [log] [blame]
/*
* drivers/amlogic/media/enhancement/amvecm/amve.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
/* #include <mach/am_regs.h> */
#include <linux/amlogic/media/utils/amstream.h>
#include <linux/amlogic/media/amvecm/ve.h>
/* #include <linux/amlogic/aml_common.h> */
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/amvecm/amvecm.h>
#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
#include <linux/amlogic/media/vout/vinfo.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include "arch/vpp_regs.h"
#include "arch/ve_regs.h"
#include "amve.h"
#include "amve_gamma_table.h"
#include <linux/io.h>
#include "dnlp_cal.h"
#include "local_contrast.h"
#define pr_amve_dbg(fmt, args...)\
do {\
if (amve_debug&0x1)\
pr_info("AMVE: " fmt, ## args);\
} while (0)\
/* #define pr_amve_error(fmt, args...) */
/* printk(KERN_##(KERN_INFO) "AMVECM: " fmt, ## args) */
#define GAMMA_RETRY 1000
/* 0: Invalid */
/* 1: Valid */
/* 2: Updated in 2D mode */
/* 3: Updated in 3D mode */
unsigned long flags;
/* #if (MESON_CPU_TYPE>=MESON_CPU_TYPE_MESONG9TV) */
#define NEW_DNLP_IN_SHARPNESS 2
#define NEW_DNLP_IN_VPP 1
unsigned int dnlp_sel = NEW_DNLP_IN_SHARPNESS;
module_param(dnlp_sel, int, 0664);
MODULE_PARM_DESC(dnlp_sel, "dnlp_sel");
/* #endif */
static int amve_debug;
module_param(amve_debug, int, 0664);
MODULE_PARM_DESC(amve_debug, "amve_debug");
struct ve_hist_s video_ve_hist;
unsigned int vpp_log[128][10];
struct tcon_gamma_table_s video_gamma_table_r;
struct tcon_gamma_table_s video_gamma_table_g;
struct tcon_gamma_table_s video_gamma_table_b;
struct tcon_gamma_table_s video_gamma_table_r_adj;
struct tcon_gamma_table_s video_gamma_table_g_adj;
struct tcon_gamma_table_s video_gamma_table_b_adj;
struct tcon_gamma_table_s video_gamma_table_ioctl_set;
struct tcon_rgb_ogo_s video_rgb_ogo = {
0, /* wb enable */
0, /* -1024~1023, r_pre_offset */
0, /* -1024~1023, g_pre_offset */
0, /* -1024~1023, b_pre_offset */
1024, /* 0~2047, r_gain */
1024, /* 0~2047, g_gain */
1024, /* 0~2047, b_gain */
0, /* -1024~1023, r_post_offset */
0, /* -1024~1023, g_post_offset */
0 /* -1024~1023, b_post_offset */
};
#define FLAG_LVDS_FREQ_SW1 (1 << 6)
int dnlp_en;/* 0:disabel;1:enable */
module_param(dnlp_en, int, 0664);
MODULE_PARM_DESC(dnlp_en, "\n enable or disable dnlp\n");
static int dnlp_status = 1;/* 0:done;1:todo */
int dnlp_en_2;/* 0:disabel;1:enable */
module_param(dnlp_en_2, int, 0664);
MODULE_PARM_DESC(dnlp_en_2, "\n enable or disable dnlp\n");
static int frame_lock_freq;
module_param(frame_lock_freq, int, 0664);
MODULE_PARM_DESC(frame_lock_freq, "frame_lock_50");
static int video_rgb_ogo_mode_sw;
module_param(video_rgb_ogo_mode_sw, int, 0664);
MODULE_PARM_DESC(video_rgb_ogo_mode_sw,
"enable/disable video_rgb_ogo_mode_sw");
int video_rgb_ogo_xvy_mtx;
module_param(video_rgb_ogo_xvy_mtx, int, 0664);
MODULE_PARM_DESC(video_rgb_ogo_xvy_mtx,
"enable/disable video_rgb_ogo_xvy_mtx");
int video_rgb_ogo_xvy_mtx_latch;
static unsigned int assist_cnt;/* ASSIST_SPARE8_REG1; */
/* 3d sync parts begin */
unsigned int sync_3d_h_start;
unsigned int sync_3d_h_end;
unsigned int sync_3d_v_start = 10;
unsigned int sync_3d_v_end = 20;
unsigned int sync_3d_polarity;
unsigned int sync_3d_out_inv;
unsigned int sync_3d_black_color = 0x008080;/* yuv black */
/* 3d sync to v by one enable/disable */
unsigned int sync_3d_sync_to_vbo;
/* 3d sync parts end */
unsigned int contrast_adj_sel;/*0:vdj1, 1:vd1 mtx rgb contrast*/
module_param(contrast_adj_sel, uint, 0664);
MODULE_PARM_DESC(contrast_adj_sel, "\n contrast_adj_sel\n");
/*gxlx adaptive sr level*/
static unsigned int sr_adapt_level;
module_param(sr_adapt_level, uint, 0664);
MODULE_PARM_DESC(sr_adapt_level, "\n sr_adapt_level\n");
/* *********************************************************************** */
/* *** VPP_FIQ-oriented functions **************************************** */
/* *********************************************************************** */
static void ve_hist_gamma_tgt(struct vframe_s *vf)
{
int ave_luma;
struct vframe_prop_s *p = &vf->prop;
video_ve_hist.sum = p->hist.vpp_luma_sum;
video_ve_hist.width = p->hist.vpp_width;
video_ve_hist.height = p->hist.vpp_height;
video_ve_hist.ave =
video_ve_hist.sum/(video_ve_hist.height*
video_ve_hist.width);
if (((vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) &&
(is_meson_gxtvbb_cpu())) ||
cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {
ave_luma = video_ve_hist.ave;
ave_luma = (ave_luma - 16) < 0 ? 0 : (ave_luma - 16);
video_ve_hist.ave = ave_luma*255/(235-16);
if (video_ve_hist.ave > 255)
video_ve_hist.ave = 255;
}
}
void ve_hist_gamma_reset(void)
{
if ((video_ve_hist.height != 0) ||
(video_ve_hist.width != 0))
memset(&video_ve_hist, 0, sizeof(struct ve_hist_s));
}
void ve_dnlp_load_reg(void)
{
int i;
if (dnlp_sel == NEW_DNLP_IN_SHARPNESS) {
if (is_meson_gxlx_cpu() || is_meson_txlx_cpu()) {
for (i = 0; i < 16; i++)
WRITE_VPP_REG(SRSHARP1_DNLP_00 + i,
ve_dnlp_reg[i]);
} else if (is_meson_tl1_cpu()) {
for (i = 0; i < 32; i++)
WRITE_VPP_REG(SHARP1_DNLP_00 + i,
ve_dnlp_reg_v2[i]);
} else {
for (i = 0; i < 16; i++)
WRITE_VPP_REG(SRSHARP0_DNLP_00 + i,
ve_dnlp_reg[i]);
}
} else {
for (i = 0; i < 16; i++)
WRITE_VPP_REG(VPP_DNLP_CTRL_00 + i,
ve_dnlp_reg[i]);
}
}
static void ve_dnlp_load_def_reg(void)
{
int i;
if (dnlp_sel == NEW_DNLP_IN_SHARPNESS) {
if (is_meson_gxlx_cpu() || is_meson_txlx_cpu()) {
for (i = 0; i < 16; i++)
WRITE_VPP_REG(SRSHARP1_DNLP_00 + i,
ve_dnlp_reg[i]);
} else if (is_meson_tl1_cpu()) {
for (i = 0; i < 32; i++)
WRITE_VPP_REG(SHARP1_DNLP_00 + i,
ve_dnlp_reg_v2[i]);
} else {
for (i = 0; i < 16; i++)
WRITE_VPP_REG(SRSHARP0_DNLP_00 + i,
ve_dnlp_reg[i]);
}
} else {
for (i = 0; i < 16; i++)
WRITE_VPP_REG(VPP_DNLP_CTRL_00 + i,
ve_dnlp_reg_def[i]);
}
}
void ve_on_vs(struct vframe_s *vf)
{
if (dnlp_en_2 || ve_en) {
/* calculate dnlp target data */
if (ve_dnlp_calculate_tgtx(vf)) {
/* calculate dnlp low-pass-filter data */
ve_dnlp_calculate_lpf();
/* calculate dnlp reg data */
ve_dnlp_calculate_reg();
/* load dnlp reg data */
ve_dnlp_load_reg();
}
}
ve_hist_gamma_tgt(vf);
/* sharpness process */
sharpness_process(vf);
/* */
#if 0
/* comment for duration algorithm is not based on panel vsync */
if (vf->prop.meas.vs_cycle && !frame_lock_nosm) {
if ((vecm_latch_flag & FLAG_LVDS_FREQ_SW1) &&
(vf->duration >= 1920 - 19) && (vf->duration <= 1920 + 19))
vpp_phase_lock_on_vs(vf->prop.meas.vs_cycle,
vf->prop.meas.vs_stamp,
true,
lock_range_50hz_fast,
lock_range_50hz_slow);
if ((!(vecm_latch_flag & FLAG_LVDS_FREQ_SW1)) &&
(vf->duration >= 1600 - 5) && (vf->duration <= 1600 + 13))
vpp_phase_lock_on_vs(vf->prop.meas.vs_cycle,
vf->prop.meas.vs_stamp,
false,
lock_range_60hz_fast,
lock_range_60hz_slow);
}
#endif
}
/* *********************************************************************** */
/* *** IOCTL-oriented functions ****************************************** */
/* *********************************************************************** */
void vpp_enable_lcd_gamma_table(void)
{
VSYNC_WR_MPEG_REG_BITS(L_GAMMA_CNTL_PORT, 1, GAMMA_EN, 1);
}
void vpp_disable_lcd_gamma_table(void)
{
VSYNC_WR_MPEG_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1);
}
void vpp_set_lcd_gamma_table(u16 *data, u32 rgb_mask)
{
int i;
int cnt = 0;
//unsigned long flags = 0;
if (!(READ_VPP_REG(ENCL_VIDEO_EN) & 0x1))
return;
WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT,
0, GAMMA_EN, 1);
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
cnt = 0;
WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_AUTO_INC) |
(0x1 << rgb_mask) |
(0x0 << HADR));
for (i = 0; i < 256; i++) {
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << WR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
cnt = 0;
WRITE_VPP_REG(L_GAMMA_DATA_PORT, data[i]);
}
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_AUTO_INC) |
(0x1 << rgb_mask));
VSYNC_WR_MPEG_REG_BITS(L_GAMMA_CNTL_PORT,
gamma_en, GAMMA_EN, 1);
}
void vpp_get_lcd_gamma_table(u32 rgb_mask, u16 *buf)
{
int i;
int cnt = 0;
if (!(READ_VPP_REG(ENCL_VIDEO_EN) & 0x1))
return;
pr_info("read gamma begin\n");
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
cnt = 0;
for (i = 0; i < 256; i++) {
cnt = 0;
// check L_GAMMA_ADDR_PORT can be writen before write it
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY) {
pr_err("%s ADR_RDY timeout\n", __func__);
break;
}
}
WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_RD) |
(0x0 << H_AUTO_INC) |
(0x1 << rgb_mask) |
(i << HADR));
cnt = 0;
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << RD_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY) {
pr_err("%s RD_RDY timeout\n", __func__);
break;
}
}
buf[i] = READ_VPP_REG(L_GAMMA_DATA_PORT);
}
WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_AUTO_INC) |
(0x1 << rgb_mask));
pr_info("read gamma over\n");
}
void amve_write_gamma_table(u16 *data, u32 rgb_mask)
{
int i;
int cnt = 0;
if (!(READ_VPP_REG(ENCL_VIDEO_EN) & 0x1))
return;
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
cnt = 0;
WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_AUTO_INC) |
(0x1 << rgb_mask) |
(0x0 << HADR));
for (i = 0; i < 256; i++) {
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << WR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
cnt = 0;
WRITE_VPP_REG(L_GAMMA_DATA_PORT, data[i]);
}
while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) {
udelay(10);
if (cnt++ > GAMMA_RETRY)
break;
}
WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_AUTO_INC) |
(0x1 << rgb_mask));
}
#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
#define MATRIX_5x3_COEF_SIZE 24
static int RGB709_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = {
0, 0, 0, /* pre offset */
COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765),
COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500),
COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116),
0, 0, 0, /* 10'/11'/12' */
0, 0, 0, /* 20'/21'/22' */
64, 512, 512, /* offset */
0, 0, 0 /* mode, right_shift, clip_en */
};
static int bypass_coeff[MATRIX_5x3_COEF_SIZE] = {
0, 0, 0, /* pre offset */
COEFF_NORM(1.0), COEFF_NORM(0.0), COEFF_NORM(0.0),
COEFF_NORM(0.0), COEFF_NORM(1.0), COEFF_NORM(0.0),
COEFF_NORM(0.0), COEFF_NORM(0.0), COEFF_NORM(1.0),
0, 0, 0, /* 10'/11'/12' */
0, 0, 0, /* 20'/21'/22' */
0, 0, 0, /* offset */
0, 0, 0 /* mode, right_shift, clip_en */
};
void vpp_set_rgb_ogo(struct tcon_rgb_ogo_s *p)
{
int m[24];
int i;
struct vinfo_s *vinfo = get_current_vinfo();
/* write to registers */
if (video_rgb_ogo_xvy_mtx) {
if (video_rgb_ogo_xvy_mtx_latch & MTX_BYPASS_RGB_OGO) {
memcpy(m, bypass_coeff, sizeof(int) * 24);
video_rgb_ogo_xvy_mtx_latch &= ~MTX_BYPASS_RGB_OGO;
} else if (video_rgb_ogo_xvy_mtx_latch & MTX_RGB2YUVL_RGB_OGO) {
memcpy(m, RGB709_to_YUV709l_coeff, sizeof(int) * 24);
video_rgb_ogo_xvy_mtx_latch &= ~MTX_RGB2YUVL_RGB_OGO;
} else
memcpy(m, bypass_coeff, sizeof(int) * 24);
m[3] = p->r_gain * m[3] / COEFF_NORM(1.0);
m[4] = p->g_gain * m[4] / COEFF_NORM(1.0);
m[5] = p->b_gain * m[5] / COEFF_NORM(1.0);
m[6] = p->r_gain * m[6] / COEFF_NORM(1.0);
m[7] = p->g_gain * m[7] / COEFF_NORM(1.0);
m[8] = p->b_gain * m[8] / COEFF_NORM(1.0);
m[9] = p->r_gain * m[9] / COEFF_NORM(1.0);
m[10] = p->g_gain * m[10] / COEFF_NORM(1.0);
m[11] = p->b_gain * m[11] / COEFF_NORM(1.0);
if (vinfo->viu_color_fmt == COLOR_FMT_RGB444) {
m[18] = (p->r_pre_offset + m[18] + 1024)
* p->r_gain / COEFF_NORM(1.0)
- p->r_gain + p->r_post_offset;
m[19] = (p->g_pre_offset + m[19] + 1024)
* p->g_gain / COEFF_NORM(1.0)
- p->g_gain + p->g_post_offset;
m[20] = (p->b_pre_offset + m[20] + 1024)
* p->b_gain / COEFF_NORM(1.0)
- p->b_gain + p->b_post_offset;
} else {
m[0] = p->r_gain * p->r_pre_offset / COEFF_NORM(1.0) +
p->r_post_offset;
m[1] = p->g_gain * p->g_pre_offset / COEFF_NORM(1.0) +
p->g_post_offset;
m[2] = p->b_gain * p->b_pre_offset / COEFF_NORM(1.0) +
p->b_post_offset;
}
for (i = 18; i < 21; i++) {
if (m[i] > 1023)
m[i] = 1023;
if (m[i] < -1024)
m[i] = -1024;
}
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
WRITE_VPP_REG_BITS(VPP_POST_MATRIX_EN_CTRL,
p->en, 0, 1);
WRITE_VPP_REG(VPP_POST_MATRIX_PRE_OFFSET0_1,
((m[0] & 0xfff) << 16)
| (m[1] & 0xfff));
WRITE_VPP_REG(VPP_POST_MATRIX_PRE_OFFSET2,
m[2] & 0xfff);
WRITE_VPP_REG(VPP_POST_MATRIX_COEF00_01,
((m[3] & 0x1fff) << 16)
| (m[4] & 0x1fff));
WRITE_VPP_REG(VPP_POST_MATRIX_COEF02_10,
((m[5] & 0x1fff) << 16)
| (m[6] & 0x1fff));
WRITE_VPP_REG(VPP_POST_MATRIX_COEF11_12,
((m[7] & 0x1fff) << 16)
| (m[8] & 0x1fff));
WRITE_VPP_REG(VPP_POST_MATRIX_COEF20_21,
((m[9] & 0x1fff) << 16)
| (m[10] & 0x1fff));
WRITE_VPP_REG(VPP_POST_MATRIX_COEF22,
m[11] & 0x1fff);
if (m[21]) {
WRITE_VPP_REG(VPP_POST_MATRIX_COEF13_14,
((m[12] & 0x1fff) << 16)
| (m[13] & 0x1fff));
WRITE_VPP_REG(VPP_POST_MATRIX_COEF15_25,
((m[14] & 0x1fff) << 16)
| (m[17] & 0x1fff));
WRITE_VPP_REG(VPP_POST_MATRIX_COEF23_24,
((m[15] & 0x1fff) << 16)
| (m[16] & 0x1fff));
}
WRITE_VPP_REG(VPP_POST_MATRIX_OFFSET0_1,
((m[18] & 0xfff) << 16)
| (m[19] & 0xfff));
WRITE_VPP_REG(VPP_POST_MATRIX_OFFSET2,
m[20] & 0xfff);
WRITE_VPP_REG_BITS(VPP_POST_MATRIX_CLIP,
m[21], 3, 2);
WRITE_VPP_REG_BITS(VPP_POST_MATRIX_CLIP,
m[22], 5, 3);
return;
}
WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, p->en, 6, 1);
WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, 3, 8, 2);
WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1,
((m[0] & 0xfff) << 16)
| (m[1] & 0xfff));
WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2,
m[2] & 0xfff);
WRITE_VPP_REG(VPP_MATRIX_COEF00_01,
((m[3] & 0x1fff) << 16)
| (m[4] & 0x1fff));
WRITE_VPP_REG(VPP_MATRIX_COEF02_10,
((m[5] & 0x1fff) << 16)
| (m[6] & 0x1fff));
WRITE_VPP_REG(VPP_MATRIX_COEF11_12,
((m[7] & 0x1fff) << 16)
| (m[8] & 0x1fff));
WRITE_VPP_REG(VPP_MATRIX_COEF20_21,
((m[9] & 0x1fff) << 16)
| (m[10] & 0x1fff));
WRITE_VPP_REG(VPP_MATRIX_COEF22,
m[11] & 0x1fff);
if (m[21]) {
WRITE_VPP_REG(VPP_MATRIX_COEF13_14,
((m[12] & 0x1fff) << 16)
| (m[13] & 0x1fff));
WRITE_VPP_REG(VPP_MATRIX_COEF15_25,
((m[14] & 0x1fff) << 16)
| (m[17] & 0x1fff));
WRITE_VPP_REG(VPP_MATRIX_COEF23_24,
((m[15] & 0x1fff) << 16)
| (m[16] & 0x1fff));
}
WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1,
((m[18] & 0xfff) << 16)
| (m[19] & 0xfff));
WRITE_VPP_REG(VPP_MATRIX_OFFSET2,
m[20] & 0xfff);
WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
m[21], 3, 2);
WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
m[22], 5, 3);
} else {
/*for txlx and txhd, pre_offset and post_offset become 13 bit*/
if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) {
WRITE_VPP_REG(VPP_GAINOFF_CTRL0,
((p->en << 31) & 0x80000000) |
((p->r_gain << 16) & 0x07ff0000) |
((p->g_gain << 0) & 0x000007ff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL1,
((p->b_gain << 16) & 0x07ff0000) |
((p->r_post_offset << 0) & 0x00001fff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL2,
((p->g_post_offset << 16) & 0x1fff0000) |
((p->b_post_offset << 0) & 0x00001fff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL3,
((p->r_pre_offset << 16) & 0x1fff0000) |
((p->g_pre_offset << 0) & 0x00001fff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL4,
((p->b_pre_offset << 0) & 0x00001fff));
} else {
/*txl and before txl, and tl1 10bit path offset is 11bit*/
WRITE_VPP_REG(VPP_GAINOFF_CTRL0,
((p->en << 31) & 0x80000000) |
((p->r_gain << 16) & 0x07ff0000) |
((p->g_gain << 0) & 0x000007ff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL1,
((p->b_gain << 16) & 0x07ff0000) |
((p->r_post_offset << 0) & 0x000007ff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL2,
((p->g_post_offset << 16) & 0x07ff0000) |
((p->b_post_offset << 0) & 0x000007ff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL3,
((p->r_pre_offset << 16) & 0x07ff0000) |
((p->g_pre_offset << 0) & 0x000007ff));
WRITE_VPP_REG(VPP_GAINOFF_CTRL4,
((p->b_pre_offset << 0) & 0x000007ff));
}
}
}
void ve_enable_dnlp(void)
{
ve_en = 1;
/* #ifdef NEW_DNLP_IN_SHARPNESS */
/* if(dnlp_sel == NEW_DNLP_IN_SHARPNESS){ */
if (dnlp_sel == NEW_DNLP_IN_SHARPNESS) {
if (is_meson_gxlx_cpu() || is_meson_txlx_cpu())
WRITE_VPP_REG_BITS(SRSHARP1_DNLP_EN, 1, 0, 1);
else if (is_meson_tl1_cpu())
WRITE_VPP_REG_BITS(SHARP1_DNLP_EN, 1, 0, 1);
else
WRITE_VPP_REG_BITS(SRSHARP0_DNLP_EN, 1, 0, 1);
} else
/* #endif */
WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL,
1, DNLP_EN_BIT, DNLP_EN_WID);
}
void ve_disable_dnlp(void)
{
ve_en = 0;
if (dnlp_sel == NEW_DNLP_IN_SHARPNESS)
if (is_meson_gxlx_cpu() || is_meson_txlx_cpu())
WRITE_VPP_REG_BITS(SRSHARP1_DNLP_EN, 0, 0, 1);
else if (is_meson_tl1_cpu())
WRITE_VPP_REG_BITS(SHARP1_DNLP_EN, 0, 0, 1);
else
WRITE_VPP_REG_BITS(SRSHARP0_DNLP_EN, 0, 0, 1);
else
WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL,
0, DNLP_EN_BIT, DNLP_EN_WID);
}
void ve_set_dnlp_2(void)
{
ulong i = 0;
/* clear historic luma sum */
if (dnlp_insmod_ok == 0)
return;
*ve_dnlp_luma_sum_copy = 0;
/* init tgt & lpf */
for (i = 0; i < 64; i++) {
ve_dnlp_tgt_copy[i] = i << 2;
ve_dnlp_lpf[i] = (ulong)ve_dnlp_tgt_copy[i] << ve_dnlp_rt;
}
/* calculate dnlp reg data */
ve_dnlp_calculate_reg();
/* load dnlp reg data */
/*ve_dnlp_load_reg();*/
ve_dnlp_load_def_reg();
}
unsigned int ve_get_vs_cnt(void)
{
return READ_VPP_REG(VPP_VDO_MEAS_VS_COUNT_LO);
}
void vpp_phase_lock_on_vs(unsigned int cycle,
unsigned int stamp,
bool lock50,
unsigned int range_fast,
unsigned int range_slow)
{
unsigned int vtotal_ori = READ_VPP_REG(ENCL_VIDEO_MAX_LNCNT);
unsigned int vtotal = lock50 ? 1349 : 1124;
unsigned int stamp_in = READ_VPP_REG(VDIN_MEAS_VS_COUNT_LO);
unsigned int stamp_out = ve_get_vs_cnt();
unsigned int phase = 0;
unsigned int cnt = assist_cnt;/* READ_VPP_REG(ASSIST_SPARE8_REG1); */
int step = 0, i = 0;
/* get phase */
if (stamp_out < stamp)
phase = 0xffffffff - stamp + stamp_out + 1;
else
phase = stamp_out - stamp;
while (phase >= cycle)
phase -= cycle;
/* 225~315 degree => tune fast panel output */
if ((phase > ((cycle * 5) >> 3)) && (phase < ((cycle * 7) >> 3))) {
vtotal -= range_slow;
step = 1;
} else if ((phase > (cycle >> 3)) && (phase < ((cycle * 3) >> 3))) {
/* 45~135 degree => tune slow panel output */
vtotal += range_slow;
step = -1;
} else if (phase >= ((cycle * 7) >> 3)) {
/* 315~360 degree => tune fast panel output */
vtotal -= range_fast;
step = + 2;
} else if (phase <= (cycle >> 3)) {
/* 0~45 degree => tune slow panel output */
vtotal += range_fast;
step = -2;
} else {/* 135~225 degree => keep still */
vtotal = vtotal_ori;
step = 0;
}
if (vtotal != vtotal_ori)
WRITE_VPP_REG(ENCL_VIDEO_MAX_LNCNT, vtotal);
if (cnt) {
cnt--;
/* WRITE_VPP_REG(ASSIST_SPARE8_REG1, cnt); */
assist_cnt = cnt;
if (cnt) {
vpp_log[cnt][0] = stamp;
vpp_log[cnt][1] = stamp_in;
vpp_log[cnt][2] = stamp_out;
vpp_log[cnt][3] = cycle;
vpp_log[cnt][4] = phase;
vpp_log[cnt][5] = vtotal;
vpp_log[cnt][6] = step;
} else {
for (i = 127; i > 0; i--) {
pr_amve_dbg("Ti=%10u Tio=%10u To=%10u CY=%6u ",
vpp_log[i][0],
vpp_log[i][1],
vpp_log[i][2],
vpp_log[i][3]);
pr_amve_dbg("PH =%10u Vt=%4u S=%2d\n",
vpp_log[i][4],
vpp_log[i][5],
vpp_log[i][6]);
}
}
}
}
void ve_frame_size_patch(unsigned int width, unsigned int height)
{
unsigned int vpp_size = height|(width << 16);
if (READ_VPP_REG(VPP_VE_H_V_SIZE) != vpp_size)
WRITE_VPP_REG(VPP_VE_H_V_SIZE, vpp_size);
}
void ve_dnlp_latch_process(void)
{
if (vecm_latch_flag & FLAG_VE_NEW_DNLP) {
vecm_latch_flag &= ~FLAG_VE_NEW_DNLP;
ve_set_v3_dnlp(&dnlp_curve_param_load);
}
if (dnlp_en && dnlp_status) {
dnlp_status = 0;
ve_set_dnlp_2();
ve_enable_dnlp();
pr_amve_dbg("\n[amve..] set vpp_enable_dnlp OK!!!\n");
} else if (dnlp_en == 0) {
dnlp_status = 1;
ve_disable_dnlp();
pr_amve_dbg("\n[amve..] set vpp_disable_dnlp OK!!!\n");
}
}
void ve_lc_latch_process(void)
{
if (vecm_latch_flag & FLAG_VE_LC_CURV) {
vecm_latch_flag &= ~FLAG_VE_LC_CURV;
lc_load_curve(&lc_curve_parm_load);
}
}
void ve_lcd_gamma_process(void)
{
if (vecm_latch_flag & FLAG_GAMMA_TABLE_R) {
vecm_latch_flag &= ~FLAG_GAMMA_TABLE_R;
vpp_set_lcd_gamma_table(video_gamma_table_r.data, H_SEL_R);
gamma_working = true;
pr_amve_dbg("\n[amve..] set vpp_set_lcd_gamma_table OK!!!\n");
}
if (vecm_latch_flag & FLAG_GAMMA_TABLE_G) {
vecm_latch_flag &= ~FLAG_GAMMA_TABLE_G;
vpp_set_lcd_gamma_table(video_gamma_table_g.data, H_SEL_G);
gamma_working = true;
pr_amve_dbg("\n[amve..] set vpp_set_lcd_gamma_table OK!!!\n");
}
if (vecm_latch_flag & FLAG_GAMMA_TABLE_B) {
vecm_latch_flag &= ~FLAG_GAMMA_TABLE_B;
vpp_set_lcd_gamma_table(video_gamma_table_b.data, H_SEL_B);
gamma_working = true;
pr_amve_dbg("\n[amve..] set vpp_set_lcd_gamma_table OK!!!\n");
}
if (vecm_latch_flag & FLAG_GAMMA_TABLE_EN) {
vecm_latch_flag &= ~FLAG_GAMMA_TABLE_EN;
vpp_enable_lcd_gamma_table();
gamma_working = true;
pr_amve_dbg("\n[amve..] set vpp_enable_lcd_gamma_table OK!!!\n");
}
if (vecm_latch_flag & FLAG_GAMMA_TABLE_DIS) {
vecm_latch_flag &= ~FLAG_GAMMA_TABLE_DIS;
vpp_disable_lcd_gamma_table();
gamma_working = false;
pr_amve_dbg("\n[amve..] set vpp_disable_lcd_gamma_table OK!!!\n");
}
if (vecm_latch_flag & FLAG_RGB_OGO) {
vecm_latch_flag &= ~FLAG_RGB_OGO;
if (video_rgb_ogo_mode_sw) {
if (video_rgb_ogo.en) {
vpp_set_lcd_gamma_table(
video_gamma_table_r_adj.data,
H_SEL_R);
vpp_set_lcd_gamma_table(
video_gamma_table_g_adj.data,
H_SEL_G);
vpp_set_lcd_gamma_table(
video_gamma_table_b_adj.data,
H_SEL_B);
} else {
vpp_set_lcd_gamma_table(
video_gamma_table_r.data,
H_SEL_R);
vpp_set_lcd_gamma_table(
video_gamma_table_g.data,
H_SEL_G);
vpp_set_lcd_gamma_table(
video_gamma_table_b.data,
H_SEL_B);
}
pr_amve_dbg("\n[amve..] set vpp_set_lcd_gamma_table OK!!!\n");
} else {
vpp_set_rgb_ogo(&video_rgb_ogo);
pr_amve_dbg("\n[amve..] set vpp_set_rgb_ogo OK!!!\n");
}
}
}
void lvds_freq_process(void)
{
/* #if ((MESON_CPU_TYPE==MESON_CPU_TYPE_MESON6TV)|| */
/* (MESON_CPU_TYPE==MESON_CPU_TYPE_MESON6TVD)) */
/* lvds freq 50Hz/60Hz */
/* if (frame_lock_freq == 1){//50 hz */
/* // panel freq is 60Hz => change back to 50Hz */
/* if (READ_VPP_REG(ENCP_VIDEO_MAX_LNCNT) < 1237) */
/* (1124 + 1349 +1) / 2 */
/* WRITE_VPP_REG(ENCP_VIDEO_MAX_LNCNT, 1349); */
/* } */
/* else if (frame_lock_freq == 2){//60 hz */
/* // panel freq is 50Hz => change back to 60Hz */
/* if(READ_VPP_REG(ENCP_VIDEO_MAX_LNCNT) >= 1237) */
/* (1124 + 1349 + 1) / 2 */
/* WRITE_VPP_REG(ENCP_VIDEO_MAX_LNCNT, 1124); */
/* } */
/* else if (frame_lock_freq == 0){ */
/* lvds freq 50Hz/60Hz */
/* if (vecm_latch_flag & FLAG_LVDS_FREQ_SW){ //50 hz */
/* // panel freq is 60Hz => change back to 50Hz */
/* if (READ_VPP_REG(ENCP_VIDEO_MAX_LNCNT) < 1237) */
/* (1124 + 1349 +1) / 2 */
/* WRITE_VPP_REG(ENCP_VIDEO_MAX_LNCNT, 1349); */
/* }else{ //60 hz */
/* // panel freq is 50Hz => change back to 60Hz */
/* if (READ_VPP_REG(ENCP_VIDEO_MAX_LNCNT) >= 1237) */
/* (1124 + 1349 + 1) / 2 */
/* WRITE_VPP_REG(ENCP_VIDEO_MAX_LNCNT, 1124); */
/* } */
/* } */
/* #endif */
}
void ve_dnlp_param_update(void)
{
vecm_latch_flag |= FLAG_VE_DNLP;
}
void ve_new_dnlp_param_update(void)
{
vecm_latch_flag |= FLAG_VE_NEW_DNLP;
}
void ve_lc_curve_update(void)
{
vecm_latch_flag |= FLAG_VE_LC_CURV;
}
static void video_data_limitation(int *val)
{
if (*val > 1023)
*val = 1023;
if (*val < 0)
*val = 0;
}
static void video_lookup(struct tcon_gamma_table_s *tbl, int *val)
{
unsigned int idx = (*val) >> 2, mod = (*val) & 3;
if (idx < 255)
*val = tbl->data[idx] +
(((tbl->data[idx + 1] - tbl->data[idx]) * mod + 2) >> 2);
else
*val = tbl->data[idx] +
(((1023 - tbl->data[idx]) * mod + 2) >> 2);
}
static void video_set_rgb_ogo(void)
{
int i = 0, r = 0, g = 0, b = 0;
for (i = 0; i < 256; i++) {
r = video_curve_2d2.data[i];
g = video_curve_2d2.data[i];
b = video_curve_2d2.data[i];
/* Pre_offset */
r += video_rgb_ogo.r_pre_offset;
g += video_rgb_ogo.g_pre_offset;
b += video_rgb_ogo.b_pre_offset;
video_data_limitation(&r);
video_data_limitation(&g);
video_data_limitation(&b);
/* Gain */
r *= video_rgb_ogo.r_gain;
r >>= 10;
g *= video_rgb_ogo.g_gain;
g >>= 10;
b *= video_rgb_ogo.b_gain;
b >>= 10;
video_data_limitation(&r);
video_data_limitation(&g);
video_data_limitation(&b);
/* Post_offset */
r += video_rgb_ogo.r_post_offset;
g += video_rgb_ogo.g_post_offset;
b += video_rgb_ogo.b_post_offset;
video_data_limitation(&r);
video_data_limitation(&g);
video_data_limitation(&b);
video_lookup(&video_curve_2d2_inv, &r);
video_lookup(&video_curve_2d2_inv, &g);
video_lookup(&video_curve_2d2_inv, &b);
/* Get gamma_ogo = curve_2d2_inv_ogo * gamma */
video_lookup(&video_gamma_table_r, &r);
video_lookup(&video_gamma_table_g, &g);
video_lookup(&video_gamma_table_b, &b);
/* Save gamma_ogo */
video_gamma_table_r_adj.data[i] = r;
video_gamma_table_g_adj.data[i] = g;
video_gamma_table_b_adj.data[i] = b;
}
}
void ve_ogo_param_update(void)
{
if (video_rgb_ogo.en > 1)
video_rgb_ogo.en = 1;
if (video_rgb_ogo.r_pre_offset > 1023)
video_rgb_ogo.r_pre_offset = 1023;
if (video_rgb_ogo.r_pre_offset < -1024)
video_rgb_ogo.r_pre_offset = -1024;
if (video_rgb_ogo.g_pre_offset > 1023)
video_rgb_ogo.g_pre_offset = 1023;
if (video_rgb_ogo.g_pre_offset < -1024)
video_rgb_ogo.g_pre_offset = -1024;
if (video_rgb_ogo.b_pre_offset > 1023)
video_rgb_ogo.b_pre_offset = 1023;
if (video_rgb_ogo.b_pre_offset < -1024)
video_rgb_ogo.b_pre_offset = -1024;
if (video_rgb_ogo.r_gain > 2047)
video_rgb_ogo.r_gain = 2047;
if (video_rgb_ogo.g_gain > 2047)
video_rgb_ogo.g_gain = 2047;
if (video_rgb_ogo.b_gain > 2047)
video_rgb_ogo.b_gain = 2047;
if (video_rgb_ogo.r_post_offset > 1023)
video_rgb_ogo.r_post_offset = 1023;
if (video_rgb_ogo.r_post_offset < -1024)
video_rgb_ogo.r_post_offset = -1024;
if (video_rgb_ogo.g_post_offset > 1023)
video_rgb_ogo.g_post_offset = 1023;
if (video_rgb_ogo.g_post_offset < -1024)
video_rgb_ogo.g_post_offset = -1024;
if (video_rgb_ogo.b_post_offset > 1023)
video_rgb_ogo.b_post_offset = 1023;
if (video_rgb_ogo.b_post_offset < -1024)
video_rgb_ogo.b_post_offset = -1024;
if (video_rgb_ogo_mode_sw)
video_set_rgb_ogo();
vecm_latch_flag |= FLAG_RGB_OGO;
}
/* sharpness process begin */
void sharpness_process(struct vframe_s *vf)
{
return;
}
/* sharpness process end */
/*for gxbbtv rgb contrast adj in vd1 matrix */
void vpp_vd1_mtx_rgb_contrast(signed int cont_val, struct vframe_s *vf)
{
unsigned int vd1_contrast;
unsigned int con_minus_value, rgb_con_en;
if ((cont_val > 1023) || (cont_val < -1024))
return;
cont_val = cont_val + 1024;
/*close rgb contrast protect*/
WRITE_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 0, 0, 1);
/*VPP_VADJ_CTRL bit 1 on for rgb contrast adj*/
rgb_con_en = READ_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 1, 1);
if (!rgb_con_en)
WRITE_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 1, 1, 1);
/*select full or limit range setting*/
con_minus_value = READ_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 4, 10);
if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) {
if (con_minus_value != 64)
WRITE_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 64, 4, 10);
} else {
if (con_minus_value != 0)
WRITE_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 0, 4, 10);
}
vd1_contrast = (READ_VPP_REG(XVYCC_VD1_RGB_CTRST) & 0xf000ffff) |
(cont_val << 16);
WRITE_VPP_REG(XVYCC_VD1_RGB_CTRST, vd1_contrast);
}
/*for gxbbtv contrast adj in vadj1*/
void vpp_vd_adj1_contrast(signed int cont_val, struct vframe_s *vf)
{
unsigned int vd1_contrast;
unsigned int vdj1_ctl;
if ((cont_val > 1023) || (cont_val < -1024))
return;
cont_val = ((cont_val + 1024) >> 3);
/*VPP_VADJ_CTRL bit 1 off for contrast adj*/
vdj1_ctl = READ_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 1);
if (is_meson_gxtvbb_cpu()) {
if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) {
if (!vdj1_ctl)
WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 1, 1);
} else {
if (vdj1_ctl)
WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 0, 1, 1);
}
}
if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) {
vd1_contrast = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0x7ff00) |
(cont_val << 0);
WRITE_VPP_REG(VPP_VADJ1_Y_2, vd1_contrast);
return;
} else if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) {
vd1_contrast = (READ_VPP_REG(VPP_VADJ1_Y) & 0x3ff00) |
(cont_val << 0);
} else {
vd1_contrast = (READ_VPP_REG(VPP_VADJ1_Y) & 0x1ff00) |
(cont_val << 0);
}
WRITE_VPP_REG(VPP_VADJ1_Y, vd1_contrast);
}
void vpp_vd_adj1_brightness(signed int bri_val, struct vframe_s *vf)
{
signed int vd1_brightness;
signed int ao0 = -64;
signed int ao1 = -512;
signed int ao2 = -512;
unsigned int a01 = 0, a_2 = 0;
/* enable vd0_csc */
unsigned int ori = READ_VPP_REG(VPP_MATRIX_CTRL) | 0x00000020;
/* point to vd0_csc */
unsigned int ctl = (ori & 0xfffffcff) | 0x00000100;
if (bri_val > 1023 || bri_val < -1024)
return;
if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) {
vd1_brightness = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0xff) |
(bri_val << 8);
WRITE_VPP_REG(VPP_VADJ1_Y_2, vd1_brightness);
} else if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) {
bri_val = bri_val >> 1;
vd1_brightness = (READ_VPP_REG(VPP_VADJ1_Y) & 0xff) |
(bri_val << 8);
WRITE_VPP_REG(VPP_VADJ1_Y, vd1_brightness);
} else {
if ((vf->source_type == VFRAME_SOURCE_TYPE_TUNER) ||
(vf->source_type == VFRAME_SOURCE_TYPE_CVBS) ||
(vf->source_type == VFRAME_SOURCE_TYPE_COMP))
vd1_brightness = bri_val;
else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) {
if ((((vf->signal_type >> 29) & 0x1) == 1) &&
(((vf->signal_type >> 16) & 0xff) == 9)) {
bri_val += ao0;
if (bri_val < -1024)
bri_val = -1024;
vd1_brightness = bri_val;
} else
vd1_brightness = bri_val;
} else {
bri_val += ao0;
if (bri_val < -1024)
bri_val = -1024;
vd1_brightness = bri_val;
}
a01 = ((vd1_brightness << 16) & 0x0fff0000) |
((ao1 << 0) & 0x00000fff);
a_2 = ((ao2 << 0) & 0x00000fff);
/*p01 = ((po0 << 16) & 0x0fff0000) |*/
/*((po1 << 0) & 0x00000fff);*/
/*p_2 = ((po2 << 0) & 0x00000fff);*/
WRITE_VPP_REG(VPP_MATRIX_CTRL, ctl);
WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1, a01);
WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2, a_2);
WRITE_VPP_REG(VPP_MATRIX_CTRL, ori);
}
}
/* brightness/contrast adjust process begin */
static void vd1_brightness_contrast(signed int brightness,
signed int contrast)
{
signed int ao0 = -64, g00 = 1024, g01 = 0, g02 = 0, po0 = 64;
signed int ao1 = -512, g10 = 0, g11 = 1024, g12 = 0, po1 = 512;
signed int ao2 = -512, g20 = 0, g21 = 0, g22 = 1024, po2 = 512;
unsigned int gc0 = 0, gc1 = 0, gc2 = 0, gc3 = 0, gc4 = 0;
unsigned int a01 = 0, a_2 = 0, p01 = 0, p_2 = 0;
/* enable vd0_csc */
unsigned int ori = READ_VPP_REG(VPP_MATRIX_CTRL) | 0x00000020;
/* point to vd0_csc */
unsigned int ctl = (ori & 0xfffffcff) | 0x00000100;
po0 += brightness >> 1;
if (po0 > 1023)
po0 = 1023;
if (po0 < -1024)
po0 = -1024;
g00 *= contrast + 2048;
g00 >>= 11;
if (g00 > 4095)
g00 = 4095;
if (g00 < -4096)
g00 = -4096;
if (contrast < 0) {
g11 *= contrast + 2048;
g11 >>= 11;
}
if (brightness < 0) {
g11 += brightness >> 1;
if (g11 > 4095)
g11 = 4095;
if (g11 < -4096)
g11 = -4096;
}
if (contrast < 0) {
g22 *= contrast + 2048;
g22 >>= 11;
}
if (brightness < 0) {
g22 += brightness >> 1;
if (g22 > 4095)
g22 = 4095;
if (g22 < -4096)
g22 = -4096;
}
gc0 = ((g00 << 16) & 0x1fff0000) | ((g01 << 0) & 0x00001fff);
gc1 = ((g02 << 16) & 0x1fff0000) | ((g10 << 0) & 0x00001fff);
gc2 = ((g11 << 16) & 0x1fff0000) | ((g12 << 0) & 0x00001fff);
gc3 = ((g20 << 16) & 0x1fff0000) | ((g21 << 0) & 0x00001fff);
gc4 = ((g22 << 0) & 0x00001fff);
/* #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESONG9TV) */
if (is_meson_gxtvbb_cpu()) {
a01 = ((ao0 << 16) & 0x0fff0000) |
((ao1 << 0) & 0x00000fff);
a_2 = ((ao2 << 0) & 0x00000fff);
p01 = ((po0 << 16) & 0x0fff0000) |
((po1 << 0) & 0x00000fff);
p_2 = ((po2 << 0) & 0x00000fff);
} else {
/* #else */
a01 = ((ao0 << 16) & 0x07ff0000) |
((ao1 << 0) & 0x000007ff);
a_2 = ((ao2 << 0) & 0x000007ff);
p01 = ((po0 << 16) & 0x07ff0000) |
((po1 << 0) & 0x000007ff);
p_2 = ((po2 << 0) & 0x000007ff);
}
/* #endif */
WRITE_VPP_REG(VPP_MATRIX_CTRL, ctl);
WRITE_VPP_REG(VPP_MATRIX_COEF00_01, gc0);
WRITE_VPP_REG(VPP_MATRIX_COEF02_10, gc1);
WRITE_VPP_REG(VPP_MATRIX_COEF11_12, gc2);
WRITE_VPP_REG(VPP_MATRIX_COEF20_21, gc3);
WRITE_VPP_REG(VPP_MATRIX_COEF22, gc4);
WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1, a01);
WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2, a_2);
WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, p01);
WRITE_VPP_REG(VPP_MATRIX_OFFSET2, p_2);
WRITE_VPP_REG(VPP_MATRIX_CTRL, ori);
}
void amvecm_bricon_process(signed int bri_val,
signed int cont_val, struct vframe_s *vf)
{
if (vecm_latch_flag & FLAG_VADJ1_BRI) {
vecm_latch_flag &= ~FLAG_VADJ1_BRI;
vpp_vd_adj1_brightness(bri_val, vf);
pr_amve_dbg("\n[amve..] set vd1_brightness OK!!!\n");
if (amve_debug&0x100)
pr_info("\n[amve..]%s :brightness:%d!!!\n",
__func__, bri_val);
}
if (vecm_latch_flag & FLAG_VADJ1_CON) {
vecm_latch_flag &= ~FLAG_VADJ1_CON;
if (contrast_adj_sel)
vpp_vd1_mtx_rgb_contrast(cont_val, vf);
else
vpp_vd_adj1_contrast(cont_val, vf);
pr_amve_dbg("\n[amve..] set vd1_contrast OK!!!\n");
if (amve_debug&0x100)
pr_info("\n[amve..]%s :contrast:%d!!!\n",
__func__, cont_val);
}
if (0) { /* vecm_latch_flag & FLAG_BRI_CON) { */
vecm_latch_flag &= ~FLAG_BRI_CON;
vd1_brightness_contrast(bri_val, cont_val);
pr_amve_dbg("\n[amve..] set vd1_brightness_contrast OK!!!\n");
}
}
/* brightness/contrast adjust process end */
void amvecm_color_process(signed int sat_val,
signed int hue_val, struct vframe_s *vf)
{
if (vecm_latch_flag & FLAG_VADJ1_COLOR) {
vecm_latch_flag &= ~FLAG_VADJ1_COLOR;
vpp_vd_adj1_saturation_hue(sat_val, hue_val, vf);
if (amve_debug&0x100)
pr_info("\n[amve..]%s :saturation:%d,hue:%d!!!\n",
__func__, sat_val, hue_val);
}
}
/* saturation/hue adjust process end */
/* 3d process begin */
void amvecm_3d_black_process(void)
{
if (vecm_latch_flag & FLAG_3D_BLACK_DIS) {
/* disable reg_3dsync_enable */
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, 0, 31, 1);
WRITE_VPP_REG_BITS(VIU_MISC_CTRL0, 0, 8, 1);
WRITE_VPP_REG_BITS(VPP_BLEND_ONECOLOR_CTRL, 0, 26, 1);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, 0, 13, 1);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC2, 0, 31, 1);
vecm_latch_flag &= ~FLAG_3D_BLACK_DIS;
}
if (vecm_latch_flag & FLAG_3D_BLACK_EN) {
WRITE_VPP_REG_BITS(VIU_MISC_CTRL0, 1, 8, 1);
WRITE_VPP_REG_BITS(VPP_BLEND_ONECOLOR_CTRL, 1, 26, 1);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC2, 1, 31, 1);
WRITE_VPP_REG_BITS(VPP_BLEND_ONECOLOR_CTRL,
sync_3d_black_color&0xffffff, 0, 24);
if (sync_3d_sync_to_vbo)
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, 1, 13, 1);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, 1, 31, 1);
vecm_latch_flag &= ~FLAG_3D_BLACK_EN;
}
}
void amvecm_3d_sync_process(void)
{
if (vecm_latch_flag & FLAG_3D_SYNC_DIS) {
/* disable reg_3dsync_enable */
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, 0, 31, 1);
vecm_latch_flag &= ~FLAG_3D_SYNC_DIS;
}
if (vecm_latch_flag & FLAG_3D_SYNC_EN) {
/*select vpu pwm source clock*/
switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) {
case 0:/* ENCL */
WRITE_VPP_REG_BITS(VPU_VPU_PWM_V0, 0, 29, 2);
break;
case 1:/* ENCI */
WRITE_VPP_REG_BITS(VPU_VPU_PWM_V0, 1, 29, 2);
break;
case 2:/* ENCP */
WRITE_VPP_REG_BITS(VPU_VPU_PWM_V0, 2, 29, 2);
break;
case 3:/* ENCT */
WRITE_VPP_REG_BITS(VPU_VPU_PWM_V0, 3, 29, 2);
break;
default:
break;
}
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC2, sync_3d_h_start, 0, 13);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC2, sync_3d_h_end, 16, 13);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, sync_3d_v_start, 0, 13);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, sync_3d_v_end, 16, 13);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, sync_3d_polarity, 29, 1);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, sync_3d_out_inv, 15, 1);
WRITE_VPP_REG_BITS(VPU_VPU_3D_SYNC1, 1, 31, 1);
vecm_latch_flag &= ~FLAG_3D_SYNC_EN;
}
}
/* 3d process end */
/*gxlx sr adaptive param*/
#define SR_SD_SCALE_LEVEL 0x1
#define SR_HD_SCALE_LEVEL 0x2
#define SR_4k_LEVEL 0x4
#define SR_CVBS_LEVEL 0x8
#define SR_NOSCALE_LEVEL 0x10
static void amve_sr_reg_setting(unsigned int adaptive_level)
{
if (adaptive_level & SR_SD_SCALE_LEVEL)
am_set_regmap(&sr1reg_sd_scale);
else if (adaptive_level & SR_HD_SCALE_LEVEL)
am_set_regmap(&sr1reg_hd_scale);
else if (adaptive_level & SR_4k_LEVEL) {
amvecm_sharpness_enable(1);/*peaking*/
amvecm_sharpness_enable(3);/*lcti*/
amvecm_sharpness_enable(5);/*drtlpf theta*/
amvecm_sharpness_enable(7);/*debanding*/
amvecm_sharpness_enable(9);/*dejaggy*/
amvecm_sharpness_enable(11);/*dering*/
amvecm_sharpness_enable(13);/*drlpf*/
} else if (adaptive_level & SR_CVBS_LEVEL)
am_set_regmap(&sr1reg_cvbs);
else if (adaptive_level & SR_NOSCALE_LEVEL)
am_set_regmap(&sr1reg_hv_noscale);
}
void amve_sharpness_adaptive_setting(struct vframe_s *vf,
unsigned int sps_h_en, unsigned int sps_v_en)
{
static unsigned int adaptive_level = 1;
unsigned int cur_level;
unsigned int width, height;
struct vinfo_s *vinfo = get_current_vinfo();
if (vf == NULL)
return;
if (vinfo->mode == VMODE_CVBS)
cur_level = SR_CVBS_LEVEL;
else {
width = (vf->type & VIDTYPE_COMPRESS) ?
vf->compWidth : vf->width;
height = (vf->type & VIDTYPE_COMPRESS) ?
vf->compHeight : vf->height;
if ((sps_h_en == 1) && (sps_v_en == 1)) {
/*super scaler h and v scale up x2 */
if ((height >= 2160) && (width >= 3840))
cur_level = SR_4k_LEVEL;
else if ((height >= 720) && (width >= 1280))
cur_level = SR_HD_SCALE_LEVEL;
else
cur_level = SR_SD_SCALE_LEVEL;
} else {
/*1. super scaler no up scale */
/*2. super scaler h up scale x2*/
if ((height >= 2160) && (width >= 3840))
cur_level = SR_4k_LEVEL;
else
cur_level = SR_NOSCALE_LEVEL;
}
}
if (adaptive_level == cur_level)
return;
amve_sr_reg_setting(cur_level);
adaptive_level = cur_level;
sr_adapt_level = adaptive_level;
pr_amve_dbg("\n[amcm..]sr_adapt_level = %d :1->sd;2->hd;4->4k\n",
sr_adapt_level);
}
/*gxlx sr init*/
void amve_sharpness_init(void)
{
am_set_regmap(&sr1reg_sd_scale);
}
static int overscan_timing = TIMING_MAX;
module_param(overscan_timing, uint, 0664);
MODULE_PARM_DESC(overscan_timing, "\n overscan_control\n");
static int overscan_screen_mode = 0xff;
module_param(overscan_screen_mode, uint, 0664);
MODULE_PARM_DESC(overscan_screen_mode, "\n overscan_screen_mode\n");
static int overscan_disable;
module_param(overscan_disable, uint, 0664);
MODULE_PARM_DESC(overscan_disable, "\n overscan_disable\n");
void amvecm_fresh_overscan(struct vframe_s *vf)
{
unsigned int height = 0;
unsigned int cur_overscan_timing = 0;
unsigned int cur_fmt;
unsigned int offset = TIMING_UHD + 1;/*av&atv*/
if (overscan_disable)
return;
if (is_dolby_vision_on())
return;
if (overscan_table[0].load_flag) {
height = (vf->type & VIDTYPE_COMPRESS) ?
vf->compHeight : vf->height;
if (height <= 576)
cur_overscan_timing = TIMING_SD;
else if (height <= 720)
cur_overscan_timing = TIMING_HD;
else if (height <= 1088)
cur_overscan_timing = TIMING_FHD;
else
cur_overscan_timing = TIMING_UHD;
overscan_timing = cur_overscan_timing;
overscan_screen_mode =
overscan_table[overscan_timing].screen_mode;
vf->pic_mode.AFD_enable =
overscan_table[overscan_timing].afd_enable;
/*local play screen mode set by decoder*/
if (overscan_table[0].source == SOURCE_MPEG)
vf->pic_mode.screen_mode = 0xff;
else
vf->pic_mode.screen_mode =
overscan_table[overscan_timing].screen_mode;
vf->pic_mode.hs = overscan_table[overscan_timing].hs;
vf->pic_mode.he = overscan_table[overscan_timing].he;
vf->pic_mode.vs = overscan_table[overscan_timing].vs;
vf->pic_mode.ve = overscan_table[overscan_timing].ve;
vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE;
}
if (overscan_table[offset].load_flag) {
cur_fmt = vf->sig_fmt;
if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_M)
cur_overscan_timing = TIMING_NTST_M;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_443)
cur_overscan_timing = TIMING_NTST_443;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_I)
cur_overscan_timing = TIMING_PAL_I;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_M)
cur_overscan_timing = TIMING_PAL_M;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_60)
cur_overscan_timing = TIMING_PAL_60;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_CN)
cur_overscan_timing = TIMING_PAL_CN;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_SECAM)
cur_overscan_timing = TIMING_SECAM;
else if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_50)
cur_overscan_timing = TIMING_NTSC_50;
else
return;
overscan_timing = cur_overscan_timing;
overscan_screen_mode =
overscan_table[overscan_timing].screen_mode;
vf->pic_mode.AFD_enable =
overscan_table[overscan_timing].afd_enable;
vf->pic_mode.screen_mode = overscan_screen_mode;
vf->pic_mode.hs = overscan_table[overscan_timing].hs;
vf->pic_mode.he = overscan_table[overscan_timing].he;
vf->pic_mode.vs = overscan_table[overscan_timing].vs;
vf->pic_mode.ve = overscan_table[overscan_timing].ve;
vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE;
}
}
void amvecm_reset_overscan(void)
{
unsigned int offset = TIMING_UHD + 1;/*av&atv*/
enum ve_source_input_e source0;
source0 = overscan_table[0].source;
if (overscan_disable)
return;
if (overscan_timing != TIMING_MAX) {
overscan_timing = TIMING_MAX;
if ((source0 != SOURCE_DTV) && (source0 != SOURCE_MPEG))
overscan_table[0].load_flag = 0;
else if (!atv_source_flg)
overscan_table[offset].load_flag = 0;
if ((source0 != SOURCE_DTV) && (source0 != SOURCE_MPEG)
&& !atv_source_flg)
overscan_screen_mode = 0xff;
}
}
static int P3dlut_tab[289] = {0};
static int P3dlut_regtab[291] = {0};
/*------------------------------------------------*/
/*pLut3D[]: 17*17*17*3*12bit*/
int vpp_set_lut3d(int enable, int bLut3DLoad,
int *pLut3D, int bLut3DCheck)
{
int i;
uint32_t dwTemp, wRgb[3];
if (bLut3DLoad) {
WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 1);
WRITE_VPP_REG(VPP_LUT3D_RAM_ADDR, 0|(0<<31));
for (i = 0; i < 17*17*17; i++) {
//{comp0, comp1, comp2}
WRITE_VPP_REG(VPP_LUT3D_RAM_DATA,
((pLut3D[i*3+1]&0xfff)<<16)|
(pLut3D[i*3+2]&0xfff));
WRITE_VPP_REG(VPP_LUT3D_RAM_DATA,
(pLut3D[i*3+0]&0xfff)); /*MSB*/
}
pr_info("%s: Lut3d load ok!!\n", __func__);
}
if (bLut3DCheck) {
WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 1);
WRITE_VPP_REG(VPP_LUT3D_RAM_ADDR, 0|(1<<31));
for (i = 0; i < 17*17*17; i++) {
dwTemp = READ_VPP_REG(VPP_LUT3D_RAM_DATA);
wRgb[2] = dwTemp & 0xfff;
wRgb[1] = (dwTemp>>16)&0xfff;
dwTemp = READ_VPP_REG(VPP_LUT3D_RAM_DATA);
wRgb[0] = dwTemp & 0xfff;
if (i < 97) {
P3dlut_regtab[i*3+2] = wRgb[2];
P3dlut_regtab[i*3+1] = wRgb[1];
P3dlut_regtab[i*3+0] = wRgb[0];
}
if (wRgb[0] != pLut3D[i*3+0]) {
pr_info("%s:Error: Lut3d check error at R[%d]\n",
__func__, i);
return 1;
}
if (wRgb[1] != pLut3D[i*3+1]) {
pr_info("%s:Error: Lut3d check error at G[%d]\n",
__func__, i);
return 1;
}
if (wRgb[2] != pLut3D[i*3+2]) {
pr_info("%s:\n", __func__);
return 1;
}
}
pr_info("%s: Lut3d check ok!!\n", __func__);
}
WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0);
WRITE_VPP_REG_BITS(VPP_LUT3D_CTRL, 7, 4, 3);/*reg_lut3d_extnd_en[6:4]*/
WRITE_VPP_REG_BITS(VPP_LUT3D_CTRL, enable&0x1, 0, 1);/*reg_lut3d_en*/
pr_info("%s: Lut3d set done!!\n", __func__);
return 0;
}
static void ycbcr2rgbpc_nb(int *R, int *G, int *B,
int Y, int Cb, int Cr, int bitdepth)
{
int y = 0;
int cb = 0;
int cr = 0;
int r = 0;
int g = 0;
int b = 0;
int norm = (1<<bitdepth)-1;
y = Y - (1<<(bitdepth-4));
cb = Cb - (1<<(bitdepth-1));
cr = Cr - (1<<(bitdepth-1));
r = (298 * y + 408 * cr) / 256;
g = (298 * y - 208 * cr - 100 * cb) / 256;
b = (298 * y + 516 * cb) / 256;
if (r > norm)
r = norm;
if (g > norm)
g = norm;
if (b > norm)
b = norm;
if (r < 0)
r = 0;
if (g < 0)
g = 0;
if (b < 0)
b = 0;
*R = r;
*G = g;
*B = b;
}
/*table: use for yuv->rgb*/
void vpp_lut3d_table_init(int *pLut3D, int bitdepth)
{
int d0, d1, d2, ncmp;
unsigned int i;
int step[3]; /*steps of each input components lut-nodes*/
int max_val = (1 << bitdepth) - 1;
/*step*/
for (ncmp = 0; ncmp < 3; ncmp++)
step[ncmp] = (1 << (bitdepth - 4));
/*initialize the lut3d ad same input and output;*/
for (d0 = 0; d0 < 17; d0++) {
for (d1 = 0; d1 < 17; d1++) {
for (d2 = 0; d2 < 17; d2++) {
pLut3D[d0*17*17*3+d1*17*3+d2*3+0] =
(d0*step[0] < max_val) ?
d0*step[0] : max_val;/* 1st components*/
pLut3D[d0*17*17*3+d1*17*3+d2*3+1] =
(d1*step[1] < max_val) ?
d1*step[1] : max_val;/*2nd components*/
pLut3D[d0*17*17*3+d1*17*3+d2*3+2] =
(d2*step[2] < max_val) ?
d2*step[2] : max_val;/*3rd components*/
ycbcr2rgbpc_nb(
&pLut3D[d0*17*17*3+d1*17*3+d2*3+0],
&pLut3D[d0*17*17*3+d1*17*3+d2*3+1],
&pLut3D[d0*17*17*3+d1*17*3+d2*3+2],
pLut3D[d0*17*17*3+d1*17*3+d2*3+0],
pLut3D[d0*17*17*3+d1*17*3+d2*3+1],
pLut3D[d0*17*17*3+d1*17*3+d2*3+2],
bitdepth);
}
}
}
for (i = 0; i < 289; i++)
P3dlut_tab[i] = pLut3D[i];
}
void dump_plut3d_table(void)
{
unsigned int i, j;
pr_info("*****dump_plut3d_table:pLut3D[0]~pLut3D[288]*****\n");
for (i = 0; i < 17; i++) {
pr_info("*****dump pLut3D:17* %d*****\n", i);
for (j = 0; j < 17; j++) {
if ((j % 16) == 0)
pr_info("\n");
pr_info("%d\t", P3dlut_tab[i*17+j]);
}
}
}
void dump_plut3d_reg_table(void)
{
unsigned int i, j;
pr_info("*****dump_plut3d_reg_table:[0]~[288]*****\n");
for (i = 0; i < 17; i++) {
pr_info("*****dump pLut3D regtab:17* %d*****\n", i);
for (j = 0; j < 17; j++) {
if ((j % 16) == 0)
pr_info("\n");
pr_info("%d\t", P3dlut_regtab[i*17+j]);
}
}
}