| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * 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> */ |
| /* media module used media/registers/cpu_version.h since kernel 5.4 */ |
| #include <linux/amlogic/media/registers/cpu_version.h> |
| #include <linux/amlogic/media/vfm/vframe.h> |
| #include <linux/amlogic/media/video_sink/video.h> |
| #include <linux/amlogic/media/amvecm/amvecm.h> |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| #include <linux/amlogic/media/amdolbyvision/dolby_vision.h> |
| #endif |
| #include <linux/amlogic/media/vout/vinfo.h> |
| #include <linux/amlogic/media/vout/vout_notify.h> |
| #include <linux/amlogic/media/vout/lcd/lcd_unifykey.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" |
| #include "amcm.h" |
| #include "reg_helper.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 |
| unsigned int gamma_loadprotect_en; |
| |
| /* 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"); |
| |
| /*for fmeter en*/ |
| int fmeter_en = 1; |
| module_param(fmeter_en, int, 0664); |
| MODULE_PARM_DESC(fmeter_en, "fmeter_en"); |
| |
| 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 BIT(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"); |
| |
| int lut3d_en;/* lut3d_en enable/disable */ |
| int lut3d_order;/* 0 RGB 1 GBR */ |
| int lut3d_debug; |
| |
| 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; */ |
| |
| /*0: recovery mode |
| *1: certification mode |
| *2: bypass mode, vadj1 follow config for ui setting |
| */ |
| static int dv_pq_bypass; |
| |
| /* 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"); |
| |
| unsigned int gamma_index; |
| /* *********************************************************************** */ |
| /* *** VPP_FIQ-oriented functions **************************************** */ |
| /* *********************************************************************** */ |
| 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; |
| int dnlp_reg = 0; |
| |
| 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 (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if (!vinfo_lcd_support() || is_meson_t7_cpu()) |
| dnlp_reg = SRSHARP0_DNLP2_00; |
| else |
| dnlp_reg = SRSHARP1_DNLP2_00; |
| |
| for (i = 0; i < 32; i++) |
| WRITE_VPP_REG(dnlp_reg + 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; |
| int dnlp_reg = 0; |
| |
| 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 (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if (!vinfo_lcd_support() || is_meson_t7_cpu()) |
| dnlp_reg = SRSHARP0_DNLP2_00; |
| else |
| dnlp_reg = SRSHARP1_DNLP2_00; |
| |
| for (i = 0; i < 32; i++) |
| WRITE_VPP_REG(dnlp_reg + 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(); |
| } |
| } |
| /* sharpness process */ |
| sharpness_process(vf); |
| } |
| |
| /* *********************************************************************** */ |
| /* *** IOCTL-oriented functions ****************************************** */ |
| /* *********************************************************************** */ |
| int vpp_get_encl_viu_mux(void) |
| { |
| unsigned int temp; |
| |
| temp = READ_VPP_REG(VPU_VIU_VENC_MUX_CTRL); |
| if ((temp & 0x3) == 0) |
| return 1; |
| if (((temp >> 2) & 0x3) == 0) |
| return 2; |
| return 0; |
| } |
| |
| int vpp_get_vout_viu_mux(void) |
| { |
| unsigned int temp = 0; |
| struct vinfo_s *vinfo1, *vinfo2, *vinfo3; |
| |
| vinfo1 = NULL; |
| vinfo2 = NULL; |
| vinfo3 = NULL; |
| #ifdef CONFIG_AMLOGIC_VOUT_SERVE |
| vinfo1 = get_current_vinfo(); |
| if (vinfo1->mode == 2) { |
| temp = (vinfo1->viu_mux >> 4) & 0xf; |
| if (temp == 0) |
| temp = 1; |
| else if (temp == 1) |
| temp = 2; |
| else if (temp > 1) |
| temp = 3; |
| return temp; |
| } |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_VOUT2_SERVE |
| vinfo2 = get_current_vinfo2(); |
| if (vinfo2->mode == 2) { |
| temp = (vinfo2->viu_mux >> 4) & 0xf; |
| if (temp == 0) |
| temp = 1; |
| else if (temp == 1) |
| temp = 2; |
| else if (temp > 1) |
| temp = 3; |
| return temp; |
| } |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_VOUT3_SERVE |
| vinfo3 = get_current_vinfo3(); |
| if (vinfo3->mode == 2) { |
| temp = (vinfo3->viu_mux >> 4) & 0xf; |
| if (temp == 0) |
| temp = 1; |
| else if (temp == 1) |
| temp = 2; |
| else if (temp > 1) |
| temp = 3; |
| return temp; |
| } |
| #endif |
| |
| return temp; |
| } |
| |
| void vpp_enable_lcd_gamma_table(int viu_sel, int rdma_write) |
| { |
| unsigned int offset = 0x0; |
| |
| if (viu_sel == 0) /*venc0*/ |
| offset = 0; |
| else if (viu_sel == 1) /*venc1*/ |
| offset = 0x100; |
| else if (viu_sel == 2) /*venc2*/ |
| offset = 0x200; |
| if (cpu_after_eq_t7()) { |
| if (rdma_write) |
| VSYNC_WRITE_VPP_REG_BITS(LCD_GAMMA_CNTL_PORT0 + offset, |
| 1, L_GAMMA_EN, 1); |
| else |
| WRITE_VPP_REG_BITS(LCD_GAMMA_CNTL_PORT0 + offset, |
| 1, L_GAMMA_EN, 1); |
| return; |
| } |
| |
| if (viu_sel == 1) /* viu1 vsync rdma */ |
| VSYNC_WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 1, GAMMA_EN, 1); |
| else |
| WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 1, GAMMA_EN, 1); |
| } |
| |
| void vpp_disable_lcd_gamma_table(int viu_sel, int rdma_write) |
| { |
| unsigned int offset = 0x0; |
| |
| if (viu_sel == 0) /*venc0*/ |
| offset = 0; |
| else if (viu_sel == 1) /*venc1*/ |
| offset = 0x100; |
| else if (viu_sel == 2) /*venc2*/ |
| offset = 0x200; |
| if (cpu_after_eq_t7()) { |
| if (rdma_write) |
| VSYNC_WRITE_VPP_REG_BITS(LCD_GAMMA_CNTL_PORT0 + offset, |
| 0, L_GAMMA_EN, 1); |
| else |
| WRITE_VPP_REG_BITS(LCD_GAMMA_CNTL_PORT0 + offset, |
| 0, L_GAMMA_EN, 1); |
| return; |
| } |
| |
| if (viu_sel == 1) /* viu1 vsync rdma */ |
| VSYNC_WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1); |
| else |
| WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1); |
| } |
| |
| /*new gamma interface, start from T7*/ |
| /*data[3][256] is r/g/b 256 data |
| *rdma_write: 1 rdma write, 0 write directly |
| *rw_flag: 0 write gamma, 1: read gamma |
| */ |
| void lcd_gamma_api(unsigned int index, u16 *r_data, u16 *g_data, u16 *b_data, |
| int rdma_write, int rw_flag) |
| { |
| int i; |
| unsigned int val; |
| unsigned int offset = 0; |
| |
| /*force init gamma*/ |
| /*if (!gamma_en)*/ |
| /* return;*/ |
| |
| if (index == 0) |
| offset = 0; |
| else if (index == 1) |
| offset = 0x100; |
| else if (index == 2) |
| offset = 0x200; |
| |
| if (rw_flag) { |
| WRITE_VPP_REG(LCD_GAMMA_ADDR_PORT0 + offset, |
| (0x1 << L_H_AUTO_INC)); |
| for (i = 0; i < 256; i++) { |
| val = READ_VPP_REG(LCD_GAMMA_DATA_PORT0 + offset); |
| r_data[i] = (val >> L_GAMMA_R) & 0x3ff; |
| g_data[i] = (val >> L_GAMMA_G) & 0x3ff; |
| b_data[i] = (val >> L_GAMMA_B) & 0x3ff; |
| } |
| } else { |
| if (rdma_write) { |
| VSYNC_WRITE_VPP_REG(LCD_GAMMA_ADDR_PORT0 + offset, |
| (0x1 << L_H_AUTO_INC)); |
| for (i = 0; i < 256; i++) |
| VSYNC_WRITE_VPP_REG(LCD_GAMMA_DATA_PORT0 + |
| offset, |
| (r_data[i] << L_GAMMA_R) | (g_data[i] << L_GAMMA_G) | |
| (b_data[i] << L_GAMMA_B)); |
| } else { |
| WRITE_VPP_REG(LCD_GAMMA_ADDR_PORT0 + offset, |
| (0x1 << L_H_AUTO_INC)); |
| for (i = 0; i < 256; i++) |
| WRITE_VPP_REG(LCD_GAMMA_DATA_PORT0 + offset, |
| (r_data[i] << L_GAMMA_R) | (g_data[i] << L_GAMMA_G) | |
| (b_data[i] << L_GAMMA_B)); |
| } |
| } |
| } |
| |
| void vpp_set_lcd_gamma_table(u16 *data, u32 rgb_mask, int viu_sel) |
| { |
| int i; |
| int cnt = 0; |
| unsigned long flags = 0; |
| |
| if (!(READ_VPP_REG(ENCL_VIDEO_EN) & 0x1)) |
| return; |
| |
| spin_lock_irqsave(&vpp_lcd_gamma_lock, flags); |
| |
| if (gamma_loadprotect_en) |
| 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) | |
| (0x23 << HADR)); |
| |
| if (gamma_loadprotect_en) { |
| if (viu_sel == 1) { /* viu1 vsync rdma */ |
| VSYNC_WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, |
| gamma_en, GAMMA_EN, 1); |
| } else { /* viu2 directly write, rdma todo */ |
| WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, |
| gamma_en, GAMMA_EN, 1); |
| } |
| } |
| |
| spin_unlock_irqrestore(&vpp_lcd_gamma_lock, flags); |
| } |
| |
| u16 gamma_data_r[256] = {0}; |
| u16 gamma_data_g[256] = {0}; |
| u16 gamma_data_b[256] = {0}; |
| void vpp_get_lcd_gamma_table(u32 rgb_mask) |
| { |
| int i; |
| int cnt = 0; |
| |
| if (cpu_after_eq_t7()) { |
| lcd_gamma_api(gamma_index, gamma_data_r, |
| gamma_data_g, gamma_data_b, 0, 1); |
| return; |
| } |
| |
| 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; |
| while (!(READ_VPP_REG(L_GAMMA_CNTL_PORT) & (0x1 << ADR_RDY))) { |
| udelay(10); |
| if (cnt++ > GAMMA_RETRY) { |
| pr_info("%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_info("%s ADR_RDY timeout\n", __func__); |
| break; |
| } |
| } |
| if (rgb_mask == H_SEL_R) |
| gamma_data_r[i] = READ_VPP_REG(L_GAMMA_DATA_PORT); |
| else if (rgb_mask == H_SEL_G) |
| gamma_data_g[i] = READ_VPP_REG(L_GAMMA_DATA_PORT); |
| else if (rgb_mask == H_SEL_B) |
| gamma_data_b[i] = READ_VPP_REG(L_GAMMA_DATA_PORT); |
| } |
| WRITE_VPP_REG(L_GAMMA_ADDR_PORT, (0x1 << H_AUTO_INC) | |
| (0x1 << rgb_mask) | |
| (0x23 << HADR)); |
| pr_info("read gamma over\n"); |
| } |
| |
| void amve_write_gamma_table(u16 *data, u32 rgb_mask) |
| { |
| int i; |
| int cnt = 0; |
| unsigned long flags = 0; |
| |
| if (cpu_after_eq_t7()) { |
| lcd_gamma_api(gamma_index, gamma_data_r, |
| gamma_data_g, gamma_data_b, 0, 1); |
| if (rgb_mask == H_SEL_R) |
| memcpy(gamma_data_r, data, sizeof(u16) * 256); |
| else if (rgb_mask == H_SEL_G) |
| memcpy(gamma_data_g, data, sizeof(u16) * 256); |
| else if (rgb_mask == H_SEL_B) |
| memcpy(gamma_data_b, data, sizeof(u16) * 256); |
| lcd_gamma_api(gamma_index, gamma_data_r, |
| gamma_data_g, gamma_data_b, 0, 0); |
| return; |
| } |
| |
| if (!(READ_VPP_REG(ENCL_VIDEO_EN) & 0x1)) |
| return; |
| |
| spin_lock_irqsave(&vpp_lcd_gamma_lock, flags); |
| |
| 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) | |
| (0x23 << HADR)); |
| |
| spin_unlock_irqrestore(&vpp_lcd_gamma_lock, flags); |
| } |
| |
| #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 */ |
| }; |
| |
| #define MTX_RS 0 |
| #define MTX_ENABLE 1 |
| #define MATRIX_3x3_COEF_SIZE 17 |
| static int matrix_yuv_bypass_coef[MATRIX_3x3_COEF_SIZE] = { |
| -64, -512, -512, |
| COEFF_NORM(1.0), COEFF_NORM(0), COEFF_NORM(0), |
| COEFF_NORM(0), COEFF_NORM(1.0), COEFF_NORM(0), |
| COEFF_NORM(0), COEFF_NORM(0), COEFF_NORM(1.0), |
| 64, 512, 512, |
| MTX_RS, |
| MTX_ENABLE |
| }; |
| |
| void vpp_set_rgb_ogo(struct tcon_rgb_ogo_s *p) |
| { |
| int m[24]; |
| int i; |
| |
| /* 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_lcd_support()) { |
| 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() || |
| is_meson_tm2_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 (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) |
| if (!vinfo_lcd_support() || is_meson_t7_cpu()) |
| WRITE_VPP_REG_BITS(SRSHARP0_DNLP_EN, 1, 0, 1); |
| else |
| WRITE_VPP_REG_BITS(SRSHARP1_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 (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) |
| if (!vinfo_lcd_support() || is_meson_t7_cpu()) |
| WRITE_VPP_REG_BITS(SRSHARP0_DNLP_EN, 0, 0, 1); |
| else |
| WRITE_VPP_REG_BITS(SRSHARP1_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_tgt_10b_copy[i] = i << 4; |
| 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) |
| { |
| int viu_sel; |
| struct tcon_gamma_table_s *ptable; |
| |
| if (cpu_after_eq_t7()) { |
| viu_sel = vpp_get_vout_viu_mux(); |
| viu_sel = viu_sel - 1; |
| if (viu_sel < 0) |
| viu_sel = 0; |
| gamma_index = viu_sel; |
| } else { |
| viu_sel = vpp_get_encl_viu_mux(); |
| } |
| if (vecm_latch_flag & FLAG_GAMMA_TABLE_EN) { |
| vecm_latch_flag &= ~FLAG_GAMMA_TABLE_EN; |
| vpp_enable_lcd_gamma_table(viu_sel, 0); |
| 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(viu_sel, 0); |
| pr_amve_dbg("\n[amve..] set vpp_disable_lcd_gamma_table OK!!!\n"); |
| } |
| if ((vecm_latch_flag & FLAG_GAMMA_TABLE_R) && |
| (vecm_latch_flag & FLAG_GAMMA_TABLE_G) && |
| (vecm_latch_flag & FLAG_GAMMA_TABLE_B)) { |
| vecm_latch_flag &= ~FLAG_GAMMA_TABLE_R; |
| vecm_latch_flag &= ~FLAG_GAMMA_TABLE_G; |
| vecm_latch_flag &= ~FLAG_GAMMA_TABLE_B; |
| if (cpu_after_eq_t7()) { |
| lcd_gamma_api(gamma_index, video_gamma_table_r.data, |
| video_gamma_table_g.data, |
| video_gamma_table_b.data, |
| 1, 0); |
| } else { |
| vpp_set_lcd_gamma_table(video_gamma_table_r.data, H_SEL_R, |
| viu_sel); |
| vpp_set_lcd_gamma_table(video_gamma_table_g.data, H_SEL_G, |
| viu_sel); |
| vpp_set_lcd_gamma_table(video_gamma_table_b.data, H_SEL_B, |
| viu_sel); |
| } |
| pr_amve_dbg("\n[amve..] set vpp_set_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) { |
| ptable = &video_gamma_table_r_adj; |
| vpp_set_lcd_gamma_table(ptable->data, |
| H_SEL_R, viu_sel); |
| ptable = &video_gamma_table_g_adj; |
| vpp_set_lcd_gamma_table(ptable->data, |
| H_SEL_G, viu_sel); |
| ptable = &video_gamma_table_b_adj; |
| vpp_set_lcd_gamma_table(ptable->data, |
| H_SEL_B, viu_sel); |
| } else { |
| ptable = &video_gamma_table_r; |
| vpp_set_lcd_gamma_table(ptable->data, |
| H_SEL_R, viu_sel); |
| ptable = &video_gamma_table_g; |
| vpp_set_lcd_gamma_table(ptable->data, |
| H_SEL_G, viu_sel); |
| ptable = &video_gamma_table_b; |
| vpp_set_lcd_gamma_table(ptable->data, |
| H_SEL_B, viu_sel); |
| } |
| pr_amve_dbg("\n[amve] vpp_set_lcd_gamma_table OK\n"); |
| } else { |
| vpp_set_rgb_ogo(&video_rgb_ogo); |
| pr_amve_dbg("\n[amve] 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) |
| { |
| } |
| |
| /* 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*/ |
| VSYNC_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) |
| VSYNC_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) |
| VSYNC_WRITE_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 64, 4, 10); |
| } else { |
| if (con_minus_value != 0) |
| VSYNC_WRITE_VPP_REG_BITS(XVYCC_VD1_RGB_CTRST, 0, 4, 10); |
| } |
| |
| vd1_contrast = (READ_VPP_REG(XVYCC_VD1_RGB_CTRST) & 0xf000ffff) | |
| (cont_val << 16); |
| |
| VSYNC_WRITE_VPP_REG(XVYCC_VD1_RGB_CTRST, vd1_contrast); |
| } |
| |
| void vpp_contrast_adj_by_uv(int cont_u, int cont_v) |
| { |
| unsigned int coef00 = 0; |
| unsigned int coef01 = 0; |
| unsigned int coef02 = 0; |
| unsigned int coef10 = 0; |
| unsigned int coef11 = 0; |
| unsigned int coef12 = 0; |
| unsigned int coef20 = 0; |
| unsigned int coef21 = 0; |
| unsigned int coef22 = 0; |
| unsigned int offst0 = 0; |
| unsigned int offst1 = 0; |
| unsigned int offst2 = 0; |
| unsigned int pre_offst0 = 0; |
| unsigned int pre_offst1 = 0; |
| unsigned int pre_offst2 = 0; |
| unsigned int rs = 0; |
| unsigned int en = 0; |
| |
| coef00 = matrix_yuv_bypass_coef[3]; |
| coef01 = matrix_yuv_bypass_coef[4]; |
| coef02 = matrix_yuv_bypass_coef[5]; |
| coef10 = matrix_yuv_bypass_coef[6]; |
| coef11 = cont_u; |
| coef12 = matrix_yuv_bypass_coef[8]; |
| coef20 = matrix_yuv_bypass_coef[9]; |
| coef21 = matrix_yuv_bypass_coef[10]; |
| coef22 = cont_v; |
| pre_offst0 = matrix_yuv_bypass_coef[0]; |
| pre_offst1 = matrix_yuv_bypass_coef[1]; |
| pre_offst2 = matrix_yuv_bypass_coef[2]; |
| offst0 = matrix_yuv_bypass_coef[12]; |
| offst1 = matrix_yuv_bypass_coef[13]; |
| offst2 = matrix_yuv_bypass_coef[14]; |
| rs = matrix_yuv_bypass_coef[15]; |
| en = matrix_yuv_bypass_coef[16]; |
| |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_COEF00_01, |
| ((coef00 & 0x1fff) << 16) | (coef01 & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_COEF02_10, |
| ((coef02 & 0x1fff) << 16) | (coef10 & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_COEF11_12, |
| ((coef11 & 0x1fff) << 16) | (coef12 & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_COEF20_21, |
| ((coef20 & 0x1fff) << 16) | (coef21 & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_COEF22, |
| (coef22 & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_OFFSET0_1, |
| ((offst0 & 0xfff) << 16) | (offst1 & 0xfff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_OFFSET2, |
| (offst2 & 0xfff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_PRE_OFFSET0_1, |
| ((pre_offst0 & 0xfff) << 16) | |
| (pre_offst1 & 0xfff)); |
| VSYNC_WRITE_VPP_REG(VPP_VD1_MATRIX_PRE_OFFSET2, |
| (pre_offst2 & 0xfff)); |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VD1_MATRIX_CLIP, rs, 5, 3); |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VD1_MATRIX_EN_CTRL, en, 0, 1); |
| } |
| |
| /*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; |
| int contrast_uv; |
| int contrast_u; |
| int contrast_v; |
| |
| if (cont_val > 1023 || cont_val < -1024) |
| return; |
| contrast_uv = cont_val + 1024; |
| cont_val = ((cont_val + 1024) >> 3); |
| |
| if (contrast_uv < 1024) { |
| contrast_u = contrast_uv; |
| contrast_v = contrast_uv; |
| } else { |
| contrast_u = (0x600 - 0x400) * (contrast_uv - 0x400) / 0x400 |
| + 0x400; |
| contrast_v = contrast_uv; |
| } |
| |
| /*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()) { |
| #ifndef CONFIG_AMLOGIC_REMOVE_OLD |
| if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) { |
| if (!vdj1_ctl) |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 1, 1); |
| } else { |
| if (vdj1_ctl) |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 0, 1, 1); |
| } |
| #endif |
| } |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { |
| vd1_contrast = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0x7ff00) | |
| (cont_val << 0); |
| //VSYNC_WRITE_VPP_REG(VPP_VADJ1_Y_2, vd1_contrast); |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ1_Y_2, cont_val, 0, 8); |
| |
| vpp_contrast_adj_by_uv(contrast_u, contrast_v); |
| 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); |
| } |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ1_Y, cont_val, 0, 8); |
| } |
| |
| 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_G12A) { |
| vd1_brightness = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0xff) | |
| (bri_val << 8); |
| |
| //WRITE_VPP_REG(VPP_VADJ1_Y_2, vd1_brightness); |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ1_Y_2, bri_val, 8, 11); |
| } 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); |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ1_Y, bri_val, 8, 10); |
| } 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()) { |
| #ifndef CONFIG_AMLOGIC_REMOVE_OLD |
| a01 = ((ao0 << 16) & 0x0fff0000) | |
| ((ao1 << 0) & 0x00000fff); |
| a_2 = ((ao2 << 0) & 0x00000fff); |
| p01 = ((po0 << 16) & 0x0fff0000) | |
| ((po1 << 0) & 0x00000fff); |
| p_2 = ((po2 << 0) & 0x00000fff); |
| #endif |
| } 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) |
| 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; |
| #ifdef CONFIG_AMLOGIC_MEDIA_TVIN |
| unsigned int cur_fmt; |
| unsigned int offset = TIMING_UHD + 1;/*av&atv*/ |
| #endif |
| |
| if (overscan_disable) |
| return; |
| |
| if (overscan_table[0].load_flag) { |
| height = (vf->type & VIDTYPE_COMPRESS) ? |
| vf->compHeight : vf->height; |
| if (height <= 480) |
| cur_overscan_timing = TIMING_SD_480; |
| else if (height <= 576) |
| cur_overscan_timing = TIMING_SD_576; |
| 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 (!(vf->pic_mode.screen_mode == VIDEO_WIDEOPTION_CUSTOM && |
| vf->pic_mode.AFD_enable)) { |
| if (overscan_table[0].source == SOURCE_MPEG) |
| vf->pic_mode.screen_mode = 0xff; |
| else |
| vf->pic_mode.screen_mode = overscan_screen_mode; |
| } |
| |
| if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS && |
| vf->pic_mode.AFD_enable) { |
| 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; |
| } else { |
| 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; |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_TVIN |
| 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; |
| |
| if (!(vf->pic_mode.screen_mode == VIDEO_WIDEOPTION_CUSTOM && |
| vf->pic_mode.AFD_enable)) |
| vf->pic_mode.screen_mode = overscan_screen_mode; |
| |
| if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS && |
| vf->pic_mode.AFD_enable) { |
| 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; |
| } else { |
| 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; |
| } |
| #endif |
| if (pq_user_latch_flag & PQ_USER_OVERSCAN_RESET) { |
| pq_user_latch_flag &= ~PQ_USER_OVERSCAN_RESET; |
| vf->pic_mode.AFD_enable = 0; |
| vf->pic_mode.screen_mode = 0; |
| vf->pic_mode.hs = 0; |
| vf->pic_mode.he = 0; |
| vf->pic_mode.vs = 0; |
| vf->pic_mode.ve = 0; |
| 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}; |
| static unsigned int *plut3d; |
| static unsigned char *pkeylutall; |
| static unsigned int *pkeylut; |
| static unsigned int max_3dlut_count = 3; |
| #define LUT3DBIN_PATH "/vendor/etc/tvconfig/panel/3dlut.bin" |
| /*plut3d[]: 17*17*17*3*10bit for tl1*/ |
| /*plut3d[]: 17*17*17*3*12bit for tm2*/ |
| /*bfromkey == 0 data from input para */ |
| /*bfromkey == 1 data from unifykey */ |
| /*bfromkey == 2 data from bin file */ |
| int vpp_set_lut3d(int bfromkey, |
| int keyindex, |
| unsigned int p3dlut_in[][3], |
| int blut3dcheck) |
| { |
| #ifdef CONFIG_AMLOGIC_LCD |
| int i, key_len, key_count, ret, offset = 0; |
| #else |
| int i, key_len, key_count, offset = 0; |
| #endif |
| int d0, d1, d2, counter, size, index0, index1, idn; |
| u32 dwtemp, ctltemp, wrgb[3]; |
| unsigned int combine3 = 0; |
| struct file *fp; |
| mm_segment_t fs; |
| loff_t pos; |
| |
| if (!lut3d_en) |
| return 1; |
| |
| if (!plut3d) |
| return 1; |
| |
| /* load 3d lut from unifykey store */ |
| if (bfromkey) { |
| /* allocate a little bit more buffer than required for safety */ |
| key_len = (4914 * 5 * max_3dlut_count); |
| pkeylutall = kmalloc(key_len, GFP_KERNEL); |
| if (!pkeylutall) |
| return 1; |
| |
| pkeylut = kmalloc(4914 * sizeof(int) * 3, |
| GFP_KERNEL); |
| if (!pkeylut) { |
| kfree(pkeylutall); |
| return 1; |
| } |
| |
| if (bfromkey == 1) { |
| #ifdef CONFIG_AMLOGIC_LCD |
| ret = |
| lcd_unifykey_get_no_header("lcd_3dlut", |
| (unsigned char *)pkeylutall, |
| &key_len); |
| if (ret < 0) { |
| kfree(pkeylutall); |
| kfree(pkeylut); |
| return 1; |
| } |
| #endif |
| } else if (bfromkey == 2) { |
| fp = filp_open(LUT3DBIN_PATH, O_RDONLY, 0); |
| if (IS_ERR(fp)) { |
| kfree(pkeylutall); |
| kfree(pkeylut); |
| return 1; |
| } |
| fs = get_fs(); |
| set_fs(KERNEL_DS); |
| pos = 0; |
| key_len = vfs_read(fp, pkeylutall, key_len, &pos); |
| |
| if (key_len == 0) { |
| kfree(pkeylutall); |
| kfree(pkeylut); |
| return 1; |
| } |
| filp_close(fp, NULL); |
| set_fs(fs); |
| } |
| |
| size = (4914 * 9) / 2; |
| key_count = key_len / size; |
| if (keyindex >= key_count) { |
| pr_info("warn: key index out of range"); |
| kfree(pkeylutall); |
| kfree(pkeylut); |
| return 1; |
| } |
| |
| offset = keyindex * size; |
| counter = 0; |
| combine3 = 0; |
| for (i = 0; i < size; i += 3) { |
| combine3 = pkeylutall[offset + i]; |
| combine3 |= (pkeylutall[offset + i + 1] << 8); |
| combine3 |= (pkeylutall[offset + i + 2] << 16); |
| pkeylut[counter] = combine3 & 0xfff; |
| ++counter; |
| pkeylut[counter] = (combine3 >> 12) & 0xfff; |
| ++counter; |
| } |
| |
| if (counter != 4914 * 3) |
| pr_info("warn: key lut read size error"); |
| |
| for (d0 = 0; d0 < 17; d0++) { |
| for (d1 = 0; d1 < 17; d1++) { |
| for (d2 = 0; d2 < 17; d2++) { |
| index0 = d0 * 289 + d1 * 17 + d2; |
| index1 = d2 * 289 + d1 * 17 + d0; |
| idn = |
| lut3d_order ? index1 : index0; |
| plut3d[index0 * 3 + 0] = |
| pkeylut[idn * 3 + 0] & 0xfff; |
| plut3d[index0 * 3 + 1] = |
| pkeylut[idn * 3 + 1] & 0xfff; |
| plut3d[index0 * 3 + 2] = |
| pkeylut[idn * 3 + 2] & 0xfff; |
| } |
| } |
| } |
| |
| kfree(pkeylutall); |
| kfree(pkeylut); |
| } else { |
| if (p3dlut_in) { |
| for (d0 = 0; d0 < 17; d0++) { |
| for (d1 = 0; d1 < 17; d1++) { |
| for (d2 = 0; d2 < 17; d2++) { |
| index0 = |
| d0 * 289 + d1 * 17 + d2; |
| index1 = |
| d2 * 289 + d1 * 17 + d0; |
| idn = |
| lut3d_order ? index1 : index0; |
| plut3d[index0 * 3 + 0] = |
| p3dlut_in[idn][0] & 0xfff; |
| plut3d[index0 * 3 + 1] = |
| p3dlut_in[idn][1] & 0xfff; |
| plut3d[index0 * 3 + 2] = |
| p3dlut_in[idn][2] & 0xfff; |
| } |
| } |
| } |
| } |
| } |
| |
| ctltemp = READ_VPP_REG(VPP_LUT3D_CTRL); |
| WRITE_VPP_REG(VPP_LUT3D_CTRL, ctltemp & 0xFFFFFFFE); |
| usleep_range(16000, 16001); |
| |
| 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*/ |
| if (lut3d_debug == 1 && (i < 17 * 17)) |
| pr_info("%d: %03x %03x %03x\n", |
| i, |
| plut3d[i * 3 + 0], |
| plut3d[i * 3 + 1], |
| plut3d[i * 3 + 2]); |
| } |
| |
| 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); |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| return 1; |
| } |
| if (wrgb[1] != plut3d[i * 3 + 1]) { |
| pr_info("%s:Error: Lut3d check error at G[%d]\n", |
| __func__, i); |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| return 1; |
| } |
| if (wrgb[2] != plut3d[i * 3 + 2]) { |
| pr_info("%s:\n", __func__); |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| return 1; |
| } |
| } |
| pr_info("%s: Lut3d check ok!!\n", __func__); |
| } |
| |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| WRITE_VPP_REG(VPP_LUT3D_CTRL, ctltemp); |
| return 0; |
| } |
| |
| int vpp_write_lut3d_section(int index, int section_len, |
| unsigned int *p3dlut_section_in) |
| { |
| int i; |
| int r_offset, g_offset; |
| u32 ctltemp; |
| |
| if (!lut3d_en) |
| return 1; |
| |
| index = index * section_len / 17; |
| |
| g_offset = index % 17; |
| r_offset = index / 17; |
| |
| ctltemp = READ_VPP_REG(VPP_LUT3D_CTRL); |
| WRITE_VPP_REG(VPP_LUT3D_CTRL, ctltemp & 0xFFFFFFFE); |
| usleep_range(16000, 16001); |
| |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 1); |
| /* LUT3D_RAM_ADDR bit20:16 R, bit12:8 G, bit4:0 B */ |
| WRITE_VPP_REG(VPP_LUT3D_RAM_ADDR, |
| (r_offset << 16) | (g_offset << 8) | (0 << 31)); |
| for (i = 0; i < section_len; i++) { |
| //{comp0, comp1, comp2} |
| WRITE_VPP_REG(VPP_LUT3D_RAM_DATA, |
| ((p3dlut_section_in[i * 3 + 1] & 0xfff) << 16) | |
| (p3dlut_section_in[i * 3 + 2] & 0xfff)); |
| WRITE_VPP_REG(VPP_LUT3D_RAM_DATA, |
| (p3dlut_section_in[i * 3 + 0] & 0xfff)); /*MSB*/ |
| } |
| |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| WRITE_VPP_REG(VPP_LUT3D_CTRL, ctltemp); |
| return 0; |
| } |
| |
| int vpp_read_lut3d_section(int index, int section_len, |
| unsigned int *p3dlut_section_out) |
| { |
| int i; |
| int r_offset, g_offset; |
| u32 dwtemp; |
| |
| if (!lut3d_en) |
| return 1; |
| |
| index = index * section_len / 17; |
| |
| g_offset = index % 17; |
| r_offset = index / 17; |
| |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 1); |
| /* LUT3D_RAM_ADDR bit20:16 R, bit12:8 G, bit4:0 B */ |
| WRITE_VPP_REG(VPP_LUT3D_RAM_ADDR, |
| (r_offset << 16) | (g_offset << 8) | (1 << 31)); |
| for (i = 0; i < section_len; i++) { |
| dwtemp = READ_VPP_REG(VPP_LUT3D_RAM_DATA); |
| p3dlut_section_out[i * 3 + 2] = dwtemp & 0xfff; |
| p3dlut_section_out[i * 3 + 1] = (dwtemp >> 16) & 0xfff; |
| dwtemp = READ_VPP_REG(VPP_LUT3D_RAM_DATA); |
| p3dlut_section_out[i * 3 + 0] = dwtemp & 0xfff; |
| } |
| |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| return 0; |
| } |
| |
| int vpp_enable_lut3d(int enable) |
| { |
| u32 temp; |
| |
| WRITE_VPP_REG(VPP_LUT3D_CBUS2RAM_CTRL, 0); |
| |
| temp = READ_VPP_REG(VPP_LUT3D_CTRL); |
| temp = (temp & 0xFFFFFF8E) | (enable & 0x1) | (0x7 << 4); |
| /*reg_lut3d_extnd_en[6:4]*/ |
| /*reg_lut3d_en*/ |
| WRITE_VPP_REG(VPP_LUT3D_CTRL, temp); |
| return 0; |
| } |
| |
| /*table: use for yuv->rgb*/ |
| void vpp_lut3d_table_init(int r, int g, int b) |
| { |
| int d0, d1, d2, step, max_val = 4095; |
| unsigned int i, index; |
| |
| mutex_lock(&vpp_lut3d_lock); |
| |
| plut3d = kmalloc(14739 * sizeof(int), GFP_KERNEL); |
| if (!plut3d) |
| return; |
| |
| if (is_meson_tl1_cpu() || |
| is_meson_t5d_cpu() || |
| is_meson_t5_cpu() || |
| is_meson_t3_cpu() || |
| is_meson_t5w_cpu()) |
| max_val = 1023; |
| |
| step = (max_val + 1) / 16; |
| |
| /*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++) { |
| index = |
| d0 * 17 * 17 * 3 + d1 * 17 * 3 + d2 * 3; |
| if (r < 0 || g < 0 || b < 0) { |
| /* bypass data */ |
| plut3d[index + 0] = |
| min(max_val, d0 * step); |
| plut3d[index + 1] = |
| min(max_val, d1 * step); |
| plut3d[index + 2] = |
| min(max_val, d2 * step); |
| } else { |
| plut3d[index + 0] = |
| min(max_val, r); |
| plut3d[index + 1] = |
| min(max_val, g); |
| plut3d[index + 2] = |
| min(max_val, b); |
| } |
| } |
| } |
| } |
| for (i = 0; i < 289; i++) |
| P3dlut_tab[i] = plut3d[i]; |
| } |
| |
| void vpp_lut3d_table_release(void) |
| { |
| kfree(plut3d); |
| plut3d = NULL; |
| mutex_unlock(&vpp_lut3d_lock); |
| } |
| |
| void dump_plut3d_table(void) |
| { |
| unsigned int i, j; |
| |
| pr_info("*****dump lut3d 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 lut3d 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]); |
| } |
| } |
| } |
| |
| void set_gamma_regs(int en, int sel) |
| { |
| int i; |
| int *gamma_lut = NULL; |
| |
| static int gamma_lut_default[66] = { |
| 0, 0, 0, 1, 2, 4, 6, 8, 11, 14, 17, 21, 26, 31, |
| 36, 42, 49, 55, 63, 71, 79, 88, 98, 108, 118, |
| 129, 141, 153, 166, 179, 193, 208, 223, 238, |
| 255, 271, 289, 307, 325, 344, 364, 384, 405, |
| 427, 449, 472, 495, 519, 544, 569, 595, 621, |
| 649, 676, 705, 734, 763, 794, 825, 856, 888, |
| 921, 955, 989, 1023, 0}; |
| |
| static int gamma_lut_straight[66] = { |
| 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, |
| 176, 192, 208, 224, 240, 256, 272, 288, 304, 320, |
| 336, 352, 368, 384, 400, 416, 432, 448, 464, 480, |
| 496, 512, 528, 544, 560, 576, 592, 608, 624, 640, |
| 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, |
| 816, 832, 848, 864, 880, 896, 912, 928, 944, 960, |
| 976, 992, 1008, 1023, 0}; |
| |
| if (!sel) |
| gamma_lut = gamma_lut_default; |
| else |
| gamma_lut = gamma_lut_straight; |
| |
| if (en) { |
| WRITE_VPP_REG(VPP_GAMMA_BIN_ADDR, 0); |
| for (i = 0; i < 33; i = i + 1) |
| WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, |
| (((gamma_lut[i * 2 + 1] << 2) & 0xffff) << 16 | |
| ((gamma_lut[i * 2] << 2) & 0xffff))); |
| for (i = 0; i < 33; i = i + 1) |
| WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, |
| (((gamma_lut[i * 2 + 1] << 2) & 0xffff) << 16 | |
| ((gamma_lut[i * 2] << 2) & 0xffff))); |
| for (i = 0; i < 33; i = i + 1) |
| WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, |
| (((gamma_lut[i * 2 + 1] << 2) & 0xffff) << 16 | |
| ((gamma_lut[i * 2] << 2) & 0xffff))); |
| WRITE_VPP_REG_BITS(VPP_GAMMA_CTRL, 0x3, 0, 2); |
| } |
| } |
| |
| void set_pre_gamma_reg(struct pre_gamma_table_s *pre_gma_tb) |
| { |
| int i; |
| int en; |
| |
| if (!pre_gma_tb) |
| return; |
| |
| en = ((pre_gma_tb->en & 0x1) << 1) | (pre_gma_tb->en & 0x1); |
| |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_ADDR, 0); |
| for (i = 0; i < 32; i++) |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, |
| (((pre_gma_tb->lut_r[i * 2 + 1] << 2) & 0xffff) << 16 | |
| ((pre_gma_tb->lut_r[i * 2] << 2) & 0xffff))); |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, (pre_gma_tb->lut_r[64] << 2) & 0xffff); |
| for (i = 0; i < 32; i++) |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, |
| (((pre_gma_tb->lut_g[i * 2 + 1] << 2) & 0xffff) << 16 | |
| ((pre_gma_tb->lut_g[i * 2] << 2) & 0xffff))); |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, (pre_gma_tb->lut_g[64] << 2) & 0xffff); |
| for (i = 0; i < 32; i++) |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, |
| (((pre_gma_tb->lut_b[i * 2 + 1] << 2) & 0xffff) << 16 | |
| ((pre_gma_tb->lut_b[i * 2] << 2) & 0xffff))); |
| VSYNC_WRITE_VPP_REG(VPP_GAMMA_BIN_DATA, (pre_gma_tb->lut_b[64] << 2) & 0xffff); |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_GAMMA_CTRL, en, 0, 2); |
| } |
| |
| void vpp_pst_hist_sta_config(int en, |
| enum pst_hist_mod mod, |
| enum pst_hist_pos pos, |
| struct vinfo_s *vinfo) |
| { |
| int cfg = 0; |
| unsigned int height = 0; |
| unsigned int width = 0; |
| |
| /*config*/ |
| cfg = (0 << 16) | /*rd index*/ |
| (0 << 8) | /*00: clk_en, 01: close clk, 1x: original clk*/ |
| (1 << 4) | /*pst_hist_window_en: 1: win_en*/ |
| (mod << 2) | /*pst hist model sel 2: y/r 1:U/G 0:V/B 3: max(y/r 1:U/G 0:V/B )*/ |
| (pos << 1) | /*pst hist after csc 1: rgb 0, yuv*/ |
| (en << 0);/*pst hist sta en 1: en*/ |
| WRITE_VPP_REG(VPP_PST_STA_CTRL, cfg); |
| if (vinfo) { |
| height = vinfo->height - 1; |
| width = vinfo->width - 1; |
| } |
| WRITE_VPP_REG(VPP_PST_STA_WIN_X, width << 16); |
| WRITE_VPP_REG(VPP_PST_STA_WIN_Y, height << 16); |
| } |
| |
| void vpp_pst_hist_sta_read(unsigned int *hist) |
| { |
| int i; |
| |
| WRITE_VPP_REG_BITS(VPP_PST_STA_CTRL, 0, 16, 16); |
| for (i = 0; i < 64; i++) |
| hist[i] = READ_VPP_REG(VPP_PST_STA_RO_HIST); |
| } |
| |
| void amvecm_wb_enable(int enable) |
| { |
| if (enable) { |
| wb_en = 1; |
| if (video_rgb_ogo_xvy_mtx) |
| WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, 1, 6, 1); |
| else |
| WRITE_VPP_REG_BITS(VPP_GAINOFF_CTRL0, 1, 31, 1); |
| } else { |
| wb_en = 0; |
| if (video_rgb_ogo_xvy_mtx) |
| WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, 0, 6, 1); |
| else |
| WRITE_VPP_REG_BITS(VPP_GAINOFF_CTRL0, 0, 31, 1); |
| } |
| } |
| |
| /*frequence meter init*/ |
| void amve_fmeter_init(int enable) |
| { |
| if (!enable) |
| return; |
| /*sr0 fmeter*/ |
| WRITE_VPP_REG_BITS(SRSHARP0_FMETER_CTRL, enable, 0, 1); |
| WRITE_VPP_REG_BITS(SRSHARP0_FMETER_CTRL, 0xe, 4, 4); |
| WRITE_VPP_REG_BITS(SRSHARP0_FMETER_CTRL, 0xa, 8, 4); |
| WRITE_VPP_REG(SRSHARP0_FMETER_CORING, 0x04040404); |
| WRITE_VPP_REG(SRSHARP0_FMETER_RATIO_H, 0x00040404); |
| WRITE_VPP_REG(SRSHARP0_FMETER_RATIO_V, 0x00040404); |
| WRITE_VPP_REG(SRSHARP0_FMETER_RATIO_D, 0x00040404); |
| WRITE_VPP_REG(SRSHARP0_FMETER_H_FILTER0_9TAP_0, 0xe11ddc24); |
| WRITE_VPP_REG_BITS(SRSHARP0_FMETER_H_FILTER0_9TAP_1, 0x14, 0, 10); |
| WRITE_VPP_REG(SRSHARP0_FMETER_H_FILTER1_9TAP_0, 0x20f0ed26); |
| WRITE_VPP_REG_BITS(SRSHARP0_FMETER_H_FILTER1_9TAP_1, 0xf0, 0, 10); |
| WRITE_VPP_REG(SRSHARP0_FMETER_H_FILTER2_9TAP_0, 0xe2e81932); |
| WRITE_VPP_REG_BITS(SRSHARP0_FMETER_H_FILTER2_9TAP_1, 0x04, 0, 10); |
| |
| /*sr1 fmeter*/ |
| WRITE_VPP_REG_BITS(SRSHARP1_FMETER_CTRL, enable, 0, 1); |
| WRITE_VPP_REG_BITS(SRSHARP1_FMETER_CTRL, 0xe, 4, 4); |
| WRITE_VPP_REG_BITS(SRSHARP1_FMETER_CTRL, 0xa, 8, 4); |
| WRITE_VPP_REG(SRSHARP1_FMETER_CORING, 0x04040404); |
| WRITE_VPP_REG(SRSHARP1_FMETER_RATIO_H, 0x00040404); |
| WRITE_VPP_REG(SRSHARP1_FMETER_RATIO_V, 0x00040404); |
| WRITE_VPP_REG(SRSHARP1_FMETER_RATIO_D, 0x00040404); |
| WRITE_VPP_REG(SRSHARP1_FMETER_H_FILTER0_9TAP_0, 0xe11ddc24); |
| WRITE_VPP_REG_BITS(SRSHARP1_FMETER_H_FILTER0_9TAP_1, 0x14, 0, 10); |
| WRITE_VPP_REG(SRSHARP1_FMETER_H_FILTER1_9TAP_0, 0x20f0ed26); |
| WRITE_VPP_REG_BITS(SRSHARP1_FMETER_H_FILTER1_9TAP_1, 0xf0, 0, 10); |
| WRITE_VPP_REG(SRSHARP1_FMETER_H_FILTER2_9TAP_0, 0xe2e81932); |
| WRITE_VPP_REG_BITS(SRSHARP1_FMETER_H_FILTER2_9TAP_1, 0x04, 0, 10); |
| |
| /*sr default value*/ |
| WRITE_VPP_REG(SRSHARP1_SR7_PKLONG_PF_GAIN, 0x40404040); |
| WRITE_VPP_REG_BITS(SRSHARP1_PK_OS_STATIC, 0x14, 0, 10); |
| WRITE_VPP_REG_BITS(SRSHARP1_PK_OS_STATIC, 0x14, 12, 10); |
| } |
| |
| /*frequence meter size config*/ |
| void amve_fmetersize_config(u32 sr0_w, u32 sr0_h, u32 sr1_w, u32 sr1_h) |
| { |
| static u32 pre_fm0_x_st, pre_fm0_y_end, pre_fm1_x_end, pre_fm1_y_end; |
| u32 fm0_x_st, fm0_x_end, fm0_y_st, fm0_y_end; |
| u32 fm1_x_st, fm1_x_end, fm1_y_st, fm1_y_end; |
| |
| fm0_x_st = 0; |
| fm0_x_end = sr0_w & 0x1fff; |
| fm0_y_st = 0; |
| fm0_y_end = sr0_h & 0x1fff; |
| |
| fm1_x_st = 0; |
| fm1_x_end = sr1_w & 0x1fff; |
| fm1_y_st = 0; |
| fm1_y_end = sr1_h & 0x1fff; |
| |
| if (fm0_x_end == pre_fm0_x_st && |
| fm0_y_end == pre_fm0_y_end && |
| fm1_x_end == pre_fm1_x_end && |
| fm1_y_end == pre_fm1_y_end) |
| return; |
| |
| if (fmeter_en) { |
| VSYNC_WRITE_VPP_REG(SRSHARP0_FMETER_WIN_HOR, |
| fm0_x_st | fm0_x_end << 16); |
| VSYNC_WRITE_VPP_REG(SRSHARP0_FMETER_WIN_VER, |
| fm0_y_st | fm0_y_end << 16); |
| |
| VSYNC_WRITE_VPP_REG(SRSHARP1_FMETER_WIN_HOR, |
| fm1_x_st | fm1_x_end << 16); |
| VSYNC_WRITE_VPP_REG(SRSHARP1_FMETER_WIN_VER, |
| fm1_y_st | fm1_y_end << 16); |
| |
| pre_fm0_x_st = fm0_x_end; |
| pre_fm0_y_end = fm0_y_end; |
| pre_fm1_x_end = fm1_x_end; |
| pre_fm1_y_end = fm1_y_end; |
| } |
| } |
| |
| int vpp_pq_ctrl_config(struct pq_ctrl_s pq_cfg) |
| { |
| unsigned int i; |
| VSYNC_WRITE_VPP_REG_BITS(SRSHARP0_PK_NR_ENABLE, |
| pq_cfg.sharpness0_en, 1, 1); |
| |
| VSYNC_WRITE_VPP_REG_BITS(SRSHARP1_PK_NR_ENABLE, |
| pq_cfg.sharpness1_en, 1, 1); |
| |
| if (pq_cfg.dnlp_en) { |
| ve_enable_dnlp(); |
| dnlp_en = 1; |
| } else { |
| ve_disable_dnlp(); |
| dnlp_en = 0; |
| } |
| |
| if (pq_cfg.cm_en) { |
| amcm_enable(); |
| cm_en = 1; |
| } else { |
| amcm_disable(); |
| cm_en = 0; |
| } |
| |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, |
| pq_cfg.vadj1_en, 0, 1); |
| else |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, |
| pq_cfg.vadj1_en, 0, 1); |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VD1_RGB_CTRST, |
| pq_cfg.vd1_ctrst_en, 1, 1); |
| |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, |
| pq_cfg.vadj2_en, 0, 1); |
| else |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, |
| pq_cfg.vadj2_en, 2, 1); |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_POST_RGB_CTRST, |
| pq_cfg.post_ctrst_en, 1, 1); |
| |
| amvecm_wb_enable(pq_cfg.wb_en); |
| |
| gamma_en = pq_cfg.gamma_en; |
| if (gamma_en) { |
| if (is_meson_t7_cpu()) { |
| for (i = 0; i < 3; i++) |
| vpp_enable_lcd_gamma_table(i, 1); |
| } else { |
| vpp_enable_lcd_gamma_table(0, 1); |
| } |
| } else { |
| if (is_meson_t7_cpu()) { |
| for (i = 0; i < 3; i++) |
| vpp_disable_lcd_gamma_table(i, 1); |
| } else { |
| vpp_disable_lcd_gamma_table(0, 1); |
| } |
| } |
| |
| if (pq_cfg.lc_en) { |
| lc_en = 1; |
| } else { |
| lc_en = 0; |
| if (is_meson_tl1_cpu() || |
| is_meson_tm2_cpu()) |
| lc_disable(); |
| } |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL, |
| pq_cfg.black_ext_en, 3, 1); |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL, |
| pq_cfg.chroma_cor_en, 4, 1); |
| |
| return 0; |
| } |
| |
| unsigned int skip_pq_ctrl_load(struct am_reg_s *p) |
| { |
| unsigned int ret = 0; |
| struct pq_ctrl_s cfg; |
| |
| if (dv_pq_bypass == 2) { |
| memcpy(&cfg, &dv_cfg_bypass, sizeof(struct pq_ctrl_s)); |
| cfg.vadj1_en = pq_cfg.vadj1_en; |
| } else if (dv_pq_bypass == 1) { |
| memcpy(&cfg, &dv_cfg_bypass, sizeof(struct pq_ctrl_s)); |
| } else { |
| memcpy(&cfg, &pq_cfg, sizeof(struct pq_ctrl_s)); |
| } |
| |
| if (!cfg.sharpness0_en) { |
| if (p->addr == (SRSHARP0_PK_NR_ENABLE)) { |
| ret |= 1 << 1; |
| return ret; |
| } |
| } |
| |
| if (!cfg.sharpness1_en) { |
| if (p->addr == (SRSHARP1_PK_NR_ENABLE)) { |
| ret |= 1 << 1; |
| return ret; |
| } |
| } |
| |
| if (!cfg.cm_en) { |
| if (p->addr == 0x208) { |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) |
| ret |= 1 << 0; |
| else |
| ret |= 1 << 1; |
| return ret; |
| } |
| } |
| |
| if (!cfg.vadj1_en) { |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { |
| if (p->addr == VPP_VADJ1_MISC) { |
| ret |= 1 << 0; |
| return ret; |
| } |
| } else { |
| if (p->addr == VPP_VADJ_CTRL) { |
| ret |= 1 << 0; |
| return ret; |
| } |
| } |
| } |
| |
| if (!cfg.vd1_ctrst_en) { |
| if (p->addr == VPP_VD1_RGB_CTRST) { |
| ret |= 1 << 1; |
| return ret; |
| } |
| } |
| |
| if (!cfg.vadj2_en) { |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { |
| if (p->addr == VPP_VADJ2_MISC) { |
| ret |= 1 << 0; |
| return ret; |
| } |
| } else { |
| if (p->addr == VPP_VADJ2_Y) { |
| ret |= 1 << 0; |
| return ret; |
| } |
| } |
| } |
| |
| if (!cfg.post_ctrst_en) { |
| if (p->addr == VPP_POST_RGB_CTRST) { |
| ret |= 1 << 1; |
| return ret; |
| } |
| } |
| |
| if (p->addr == VPP_VE_ENABLE_CTRL) { |
| if (!cfg.black_ext_en) |
| ret |= 1 << 3; |
| if (!cfg.chroma_cor_en) |
| ret |= 1 << 4; |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| int dv_pq_ctl(enum dv_pq_ctl_e ctl) |
| { |
| struct pq_ctrl_s cfg; |
| |
| switch (ctl) { |
| case DV_PQ_BYPASS: |
| memcpy(&cfg, &dv_cfg_bypass, sizeof(struct pq_ctrl_s)); |
| cfg.vadj1_en = pq_cfg.vadj1_en; |
| vpp_pq_ctrl_config(cfg); |
| dv_pq_bypass = 2; |
| pr_amve_dbg("dv enable, pq disable, dv_pq_bypass = %d\n", |
| dv_pq_bypass); |
| break; |
| case DV_PQ_CERT: |
| vpp_pq_ctrl_config(dv_cfg_bypass); |
| dv_pq_bypass = 1; |
| pr_amve_dbg("dv certification mode, pq disable, dv_pq_bypass = %d\n", |
| dv_pq_bypass); |
| break; |
| case DV_PQ_REC: |
| vpp_pq_ctrl_config(pq_cfg); |
| dv_pq_bypass = 0; |
| pr_amve_dbg("dv disable, pq recovery, dv_pq_bypass = %d\n", |
| dv_pq_bypass); |
| break; |
| default: |
| break; |
| } |
| return 0; |
| } |
| EXPORT_SYMBOL(dv_pq_ctl); |
| |
| int mtx_mul_mtx(int (*mtx_a)[3], int (*mtx_b)[3], int (*mtx_out)[3]) |
| { |
| int i, j, k; |
| |
| for (i = 0; i < 3; i++) { |
| for (j = 0; j < 3; j++) { |
| mtx_out[i][j] = 0; |
| for (k = 0; k < 3; k++) |
| mtx_out[i][j] += mtx_a[i][k] * mtx_b[k][j]; |
| } |
| } |
| |
| for (i = 0; i < 3; i++) { |
| for (j = 0; j < 3; j++) |
| mtx_out[i][j] = (mtx_out[i][j] + (1 << 9)) >> 10; |
| } |
| |
| return 0; |
| } |
| |
| int mtx_multi(int *rgb, int (*mtx_out)[3]) |
| { |
| int i, j; |
| int mtx_rgb[3][3] = {0}; |
| int mtx_in[3][3] = {0}; |
| int mtx_rgbto709l[3][3] = { |
| {187, 629, 63}, |
| {-103, -346, 450}, |
| {450, -409, -41}, |
| }; |
| int mtx_709ltorgb[3][3] = { |
| {1192, 0, 1836}, |
| {1192, -218, -547}, |
| {1192, 2166, 0}, |
| }; |
| |
| mtx_in[0][0] = rgb[0]; |
| mtx_in[1][1] = rgb[1]; |
| mtx_in[2][2] = rgb[2]; |
| |
| if (mtx_in[0][0] == 0x400 && |
| mtx_in[1][1] == 0x400 && |
| mtx_in[2][2] == 0x400) { |
| for (i = 0; i < 3; i++) { |
| for (j = 0; j < 3; j++) { |
| if (i == j) |
| mtx_out[i][j] = 0x400; |
| else |
| mtx_out[i][j] = 0; |
| } |
| } |
| |
| } else { |
| mtx_mul_mtx(mtx_in, mtx_709ltorgb, mtx_rgb); |
| mtx_mul_mtx(mtx_rgbto709l, mtx_rgb, mtx_out); |
| } |
| |
| for (i = 0; i < 3; i++) { |
| for (j = 0; j < 3; j++) |
| pr_amve_dbg("mtx_out[%d][%d] = 0x%x\n", |
| i, j, mtx_out[i][j]); |
| } |
| return 0; |
| } |
| |
| void eye_proc(int *rgb, int mtx_on) |
| { |
| unsigned int matrix_coef00_01 = 0; |
| unsigned int matrix_coef02_10 = 0; |
| unsigned int matrix_coef11_12 = 0; |
| unsigned int matrix_coef20_21 = 0; |
| unsigned int matrix_coef22 = 0; |
| unsigned int matrix_coef13_14 = 0; |
| unsigned int matrix_coef23_24 = 0; |
| unsigned int matrix_coef15_25 = 0; |
| unsigned int matrix_clip = 0; |
| unsigned int matrix_offset0_1 = 0; |
| unsigned int matrix_offset2 = 0; |
| unsigned int matrix_pre_offset0_1 = 0; |
| unsigned int matrix_pre_offset2 = 0; |
| unsigned int matrix_en_ctrl = 0; |
| int mtx_out[3][3] = {0}; |
| int pre_offset[3] = { |
| -64, -512, -512 |
| }; |
| |
| int offset[3] = { |
| 64, 512, 512 |
| }; |
| |
| if (vinfo_lcd_support()) |
| return; |
| |
| matrix_coef00_01 = VPP_POST_MATRIX_COEF00_01; |
| matrix_coef02_10 = VPP_POST_MATRIX_COEF02_10; |
| matrix_coef11_12 = VPP_POST_MATRIX_COEF11_12; |
| matrix_coef20_21 = VPP_POST_MATRIX_COEF20_21; |
| matrix_coef22 = VPP_POST_MATRIX_COEF22; |
| matrix_coef13_14 = VPP_POST_MATRIX_COEF13_14; |
| matrix_coef23_24 = VPP_POST_MATRIX_COEF23_24; |
| matrix_coef15_25 = VPP_POST_MATRIX_COEF15_25; |
| matrix_clip = VPP_POST_MATRIX_CLIP; |
| matrix_offset0_1 = VPP_POST_MATRIX_OFFSET0_1; |
| matrix_offset2 = VPP_POST_MATRIX_OFFSET2; |
| matrix_pre_offset0_1 = VPP_POST_MATRIX_PRE_OFFSET0_1; |
| matrix_pre_offset2 = VPP_POST_MATRIX_PRE_OFFSET2; |
| matrix_en_ctrl = VPP_POST_MATRIX_EN_CTRL; |
| |
| VSYNC_WRITE_VPP_REG_BITS(VPP_POST_MATRIX_EN_CTRL, mtx_on, 0, 1); |
| |
| if (!mtx_on) |
| return; |
| |
| mtx_multi(rgb, mtx_out); |
| VSYNC_WRITE_VPP_REG(matrix_coef00_01, |
| ((mtx_out[0][0] & 0x1fff) << 16) | (mtx_out[0][1] & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(matrix_coef02_10, |
| ((mtx_out[0][2] & 0x1fff) << 16) | (mtx_out[1][0] & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(matrix_coef11_12, |
| ((mtx_out[1][1] & 0x1fff) << 16) | (mtx_out[1][2] & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(matrix_coef20_21, |
| ((mtx_out[2][0] & 0x1fff) << 16) | (mtx_out[2][1] & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(matrix_coef22, (mtx_out[2][2] & 0x1fff)); |
| VSYNC_WRITE_VPP_REG(matrix_offset0_1, |
| ((offset[0] & 0x7ff) << 16) | (offset[1] & 0x7ff)); |
| VSYNC_WRITE_VPP_REG(matrix_offset2, (offset[2] & 0x7ff)); |
| VSYNC_WRITE_VPP_REG(matrix_pre_offset0_1, |
| ((pre_offset[0] & 0x7ff) << 16) | (pre_offset[1] & 0x7ff)); |
| VSYNC_WRITE_VPP_REG(matrix_pre_offset2, (pre_offset[2] & 0x7ff)); |
| } |
| |
| /*t3 for power consumption, disable clock |
| *modules only before post blend can be disable |
| *because after postblend it used for color temperature |
| *or color corection |
| */ |
| static void vpp_enhence_clk_ctl(int en) |
| { |
| VSYNC_WRITE_VPP_REG_BITS(VPP_GCLK_CTRL0, en, 6, 2); /*blue stretch*/ |
| VSYNC_WRITE_VPP_REG_BITS(VPP_GCLK_CTRL1, |
| (en | (en << 2)), 0, 4); /*cm*/ |
| VSYNC_WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL, |
| (en | (en << 2)), 24, 4); /*ble, chroma coring*/ |
| } |
| |
| void set_vpp_enh_clk(struct vframe_s *vf, struct vframe_s *rpt_vf) |
| { |
| /*cm / blue stretch/ black extension/ chroma coring*/ |
| /*other modules(sr0/sr1/dnlp/lc disable in amvideo)*/ |
| /*en: 1 disable clock, 0: enable clock*/ |
| static enum pw_state_e pre_state = PW_MAX; |
| enum pw_state_e pw_state = PW_MAX; |
| |
| if (get_cpu_type() < MESON_CPU_MAJOR_ID_T3) |
| return; |
| |
| if (vf || rpt_vf) |
| pw_state = PW_ON; |
| else |
| pw_state = PW_OFF; |
| |
| switch (pw_state) { |
| case PW_ON: |
| if (pre_state != PW_ON) { |
| vpp_enhence_clk_ctl(PW_ON); |
| pre_state = pw_state; |
| pr_amve_dbg("PW_ON: pre_state: %d\n", pre_state); |
| } |
| break; |
| case PW_OFF: |
| if (pre_state != PW_OFF) { |
| vpp_enhence_clk_ctl(PW_ON); |
| pre_state = pw_state; |
| pr_amve_dbg("PW_OFF: pre_state: %d\n", pre_state); |
| } |
| break; |
| case PW_MAX: |
| default: |
| pre_state = PW_MAX; |
| break; |
| } |
| } |
| |