| /* |
| * drivers/amlogic/media/video_sink/video_hw.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/version.h> |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/spinlock.h> |
| #include <linux/interrupt.h> |
| #include <linux/fs.h> |
| #include <linux/string.h> |
| #include <linux/io.h> |
| #include <linux/mm.h> |
| #include <linux/amlogic/major.h> |
| #include <linux/err.h> |
| #include <linux/mutex.h> |
| #include <linux/platform_device.h> |
| #include <linux/ctype.h> |
| #include <linux/amlogic/media/vfm/vframe.h> |
| #include <linux/amlogic/media/vfm/vframe_provider.h> |
| #include <linux/amlogic/media/vfm/vframe_receiver.h> |
| #include <linux/amlogic/media/utils/amstream.h> |
| #include <linux/amlogic/media/vout/vout_notify.h> |
| #include <linux/sched.h> |
| #include <linux/slab.h> |
| #include <linux/poll.h> |
| #include <linux/clk.h> |
| #include <linux/arm-smccc.h> |
| #include <linux/debugfs.h> |
| #include <linux/amlogic/media/canvas/canvas.h> |
| #include <linux/amlogic/media/canvas/canvas_mgr.h> |
| #include <linux/sched.h> |
| #include <linux/amlogic/media/video_sink/video_keeper.h> |
| #include "video_priv.h" |
| #include "video_reg.h" |
| |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| #include <linux/amlogic/media/amvecm/amvecm.h> |
| #endif |
| #include <linux/amlogic/media/utils/vdec_reg.h> |
| |
| #include <linux/amlogic/media/registers/register.h> |
| #include <linux/uaccess.h> |
| #include <linux/amlogic/media/utils/amports_config.h> |
| #include <linux/amlogic/media/vpu/vpu.h> |
| #include "videolog.h" |
| |
| #include <linux/amlogic/media/video_sink/vpp.h> |
| #include "linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h" |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| #include "../common/rdma/rdma.h" |
| #endif |
| #include <linux/amlogic/media/video_sink/video.h> |
| #include "../common/vfm/vfm.h" |
| #include <linux/amlogic/media/amdolbyvision/dolby_vision.h> |
| #include "video_receiver.h" |
| #ifdef CONFIG_AMLOGIC_MEDIA_LUT_DMA |
| #include <linux/amlogic/media/lut_dma/lut_dma.h> |
| #endif |
| #ifdef CONFIG_AMLOGIC_MEDIA_SECURITY |
| #include <linux/amlogic/media/vpu_secure/vpu_secure.h> |
| #endif |
| |
| /* #define DI_POST_PWR */ |
| |
| /* #define DI_POST_PWR */ |
| |
| struct video_layer_s vd_layer[MAX_VD_LAYER]; |
| struct disp_info_s glayer_info[MAX_VD_LAYERS]; |
| |
| struct video_dev_s video_dev = {0x1d00 - 0x1d00, 0x1a50 - 0x1a50}; |
| struct video_dev_s *cur_dev = &video_dev; |
| bool legacy_vpp = true; |
| |
| static bool bypass_cm; |
| bool hscaler_8tap_enable[MAX_VD_LAYER]; |
| int pre_hscaler_ntap_enable[MAX_VD_LAYER]; |
| int pre_hscaler_ntap_set[MAX_VD_LAYER]; |
| int pre_vscaler_ntap_enable[MAX_VD_LAYER]; |
| int pre_vscaler_ntap_set[MAX_VD_LAYER]; |
| |
| static DEFINE_SPINLOCK(video_onoff_lock); |
| static DEFINE_SPINLOCK(video2_onoff_lock); |
| |
| /* VPU delay work */ |
| #define VPU_DELAYWORK_VPU_VD1_CLK 1 |
| #define VPU_DELAYWORK_VPU_VD2_CLK 2 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_VD1 4 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_VD2 8 |
| #define VPU_VIDEO_LAYER1_CHANGED 0x10 |
| #define VPU_VIDEO_LAYER2_CHANGED 0x20 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_DOLBY0 0x40 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1A 0x80 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1B 0x100 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_DOLBY2 0x200 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_DOLBY_CORE3 0x400 |
| #define VPU_DELAYWORK_MEM_POWER_OFF_PRIME_DOLBY 0x800 |
| |
| #define VPU_MEM_POWEROFF_DELAY 100 |
| #define DV_MEM_POWEROFF_DELAY 2 |
| |
| static struct work_struct vpu_delay_work; |
| static int vpu_vd1_clk_level; |
| static int vpu_vd2_clk_level; |
| static DEFINE_SPINLOCK(delay_work_lock); |
| static int vpu_delay_work_flag; |
| static int vpu_mem_power_off_count; |
| static int dv_mem_power_off_count; |
| |
| #define VPU_VD1_CLK_SWITCH(level) \ |
| do { \ |
| unsigned long flags; \ |
| int next_level = (level); \ |
| if (vpu_vd1_clk_level != next_level) { \ |
| vpu_vd1_clk_level = next_level; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag |= \ |
| VPU_DELAYWORK_VPU_VD1_CLK; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| } \ |
| } while (0) |
| |
| #define VPU_VD2_CLK_SWITCH(level) \ |
| do { \ |
| unsigned long flags; \ |
| int next_level = (level); \ |
| if (vpu_vd2_clk_level != next_level) { \ |
| vpu_vd2_clk_level = next_level; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag |= \ |
| VPU_DELAYWORK_VPU_VD2_CLK; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| } \ |
| } while (0) |
| #ifdef DI_POST_PWR |
| #define VD1_MEM_POWER_ON() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag &= ~VPU_DELAYWORK_MEM_POWER_OFF_VD1; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| switch_vpu_mem_pd_vmod(VPU_VIU_VD1, VPU_MEM_POWER_ON); \ |
| switch_vpu_mem_pd_vmod(VPU_AFBC_DEC, VPU_MEM_POWER_ON); \ |
| switch_vpu_mem_pd_vmod(VPU_DI_POST, VPU_MEM_POWER_ON); \ |
| if (!legacy_vpp) { \ |
| switch_vpu_mem_pd_vmod( \ |
| VPU_VD1_SCALE, VPU_MEM_POWER_ON); \ |
| if (glayer_info[0].fgrain_support) \ |
| switch_vpu_mem_pd_vmod(VPU_FGRAIN0, \ |
| VPU_MEM_POWER_ON); \ |
| } \ |
| } while (0) |
| #else |
| #define VD1_MEM_POWER_ON() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag &= ~VPU_DELAYWORK_MEM_POWER_OFF_VD1; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| switch_vpu_mem_pd_vmod(VPU_VIU_VD1, VPU_MEM_POWER_ON); \ |
| switch_vpu_mem_pd_vmod(VPU_AFBC_DEC, VPU_MEM_POWER_ON); \ |
| if (!legacy_vpp) \ |
| switch_vpu_mem_pd_vmod( \ |
| VPU_VD1_SCALE, VPU_MEM_POWER_ON); \ |
| if (glayer_info[0].fgrain_support) \ |
| switch_vpu_mem_pd_vmod(VPU_FGRAIN0, \ |
| VPU_MEM_POWER_ON); \ |
| } while (0) |
| #endif |
| #define VD2_MEM_POWER_ON() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag &= ~VPU_DELAYWORK_MEM_POWER_OFF_VD2; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| switch_vpu_mem_pd_vmod(VPU_VIU_VD2, VPU_MEM_POWER_ON); \ |
| switch_vpu_mem_pd_vmod(VPU_AFBC_DEC1, VPU_MEM_POWER_ON); \ |
| if (!legacy_vpp) \ |
| switch_vpu_mem_pd_vmod( \ |
| VPU_VD2_SCALE, VPU_MEM_POWER_ON); \ |
| if (glayer_info[1].fgrain_support) \ |
| switch_vpu_mem_pd_vmod(VPU_FGRAIN1, \ |
| VPU_MEM_POWER_ON); \ |
| } while (0) |
| #define VD1_MEM_POWER_OFF() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag |= VPU_DELAYWORK_MEM_POWER_OFF_VD1; \ |
| vpu_mem_power_off_count = VPU_MEM_POWEROFF_DELAY; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| } while (0) |
| #define VD2_MEM_POWER_OFF() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&delay_work_lock, flags); \ |
| vpu_delay_work_flag |= VPU_DELAYWORK_MEM_POWER_OFF_VD2; \ |
| vpu_mem_power_off_count = VPU_MEM_POWEROFF_DELAY; \ |
| spin_unlock_irqrestore(&delay_work_lock, flags); \ |
| } while (0) |
| |
| #define VIDEO_LAYER_ON() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&video_onoff_lock, flags); \ |
| if (vd_layer[0].onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ |
| vd_layer[0].onoff_state = \ |
| VIDEO_ENABLE_STATE_ON_PENDING; \ |
| vd_layer[0].enabled = 1; \ |
| vd_layer[0].enabled_status_saved = 1; \ |
| spin_unlock_irqrestore(&video_onoff_lock, flags); \ |
| } while (0) |
| |
| #define VIDEO_LAYER_OFF() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&video_onoff_lock, flags); \ |
| vd_layer[0].onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ |
| vd_layer[0].enabled = 0; \ |
| vd_layer[0].enabled_status_saved = 0; \ |
| spin_unlock_irqrestore(&video_onoff_lock, flags); \ |
| } while (0) |
| |
| #define VIDEO_LAYER2_ON() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&video2_onoff_lock, flags); \ |
| if (vd_layer[1].onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ |
| vd_layer[1].onoff_state = \ |
| VIDEO_ENABLE_STATE_ON_PENDING; \ |
| vd_layer[1].enabled = 1; \ |
| vd_layer[1].enabled_status_saved = 1; \ |
| spin_unlock_irqrestore(&video2_onoff_lock, flags); \ |
| } while (0) |
| |
| #define VIDEO_LAYER2_OFF() \ |
| do { \ |
| unsigned long flags; \ |
| spin_lock_irqsave(&video2_onoff_lock, flags); \ |
| vd_layer[1].onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ |
| vd_layer[1].enabled = 0; \ |
| vd_layer[1].enabled_status_saved = 0; \ |
| spin_unlock_irqrestore(&video2_onoff_lock, flags); \ |
| } while (0) |
| |
| #define enable_video_layer() \ |
| do { \ |
| VD1_MEM_POWER_ON(); \ |
| VIDEO_LAYER_ON(); \ |
| } while (0) |
| |
| #define enable_video_layer2() \ |
| do { \ |
| VD2_MEM_POWER_ON(); \ |
| VIDEO_LAYER2_ON(); \ |
| } while (0) |
| |
| #define disable_video_layer(async) \ |
| do { \ |
| if (!(async)) { \ |
| CLEAR_VCBUS_REG_MASK( \ |
| VPP_MISC + cur_dev->vpp_off, \ |
| VPP_VD1_PREBLEND | \ |
| VPP_VD1_POSTBLEND); \ |
| if (!legacy_vpp) \ |
| WRITE_VCBUS_REG( \ |
| VD1_BLEND_SRC_CTRL + \ |
| vd_layer[0].misc_reg_offt, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[0].vd_afbc_reg.afbc_enable, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[0].vd_mif_reg.vd_if0_gen_reg, 0); \ |
| } \ |
| VIDEO_LAYER_OFF(); \ |
| VD1_MEM_POWER_OFF(); \ |
| if (vd_layer[0].global_debug & DEBUG_FLAG_BLACKOUT) { \ |
| pr_info("VIDEO: DisableVideoLayer()\n"); \ |
| } \ |
| } while (0) |
| |
| #define disable_video_layer2(async) \ |
| do { \ |
| if (!(async)) { \ |
| CLEAR_VCBUS_REG_MASK( \ |
| VPP_MISC + cur_dev->vpp_off, \ |
| VPP_VD2_POSTBLEND | \ |
| VPP_VD2_PREBLEND); \ |
| if (!legacy_vpp) \ |
| WRITE_VCBUS_REG( \ |
| VD2_BLEND_SRC_CTRL + \ |
| vd_layer[1].misc_reg_offt, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[1].vd_afbc_reg.afbc_enable, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[1].vd_mif_reg.vd_if0_gen_reg, 0); \ |
| } \ |
| VIDEO_LAYER2_OFF(); \ |
| VD2_MEM_POWER_OFF(); \ |
| if (vd_layer[1].global_debug & DEBUG_FLAG_BLACKOUT) { \ |
| pr_info("VIDEO: DisableVideoLayer2()\n"); \ |
| } \ |
| } while (0) |
| |
| #define disable_video_all_layer_nodelay() \ |
| do { \ |
| CLEAR_VCBUS_REG_MASK( \ |
| VPP_MISC + cur_dev->vpp_off, \ |
| VPP_VD1_PREBLEND | VPP_VD2_PREBLEND |\ |
| VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND); \ |
| if (!legacy_vpp) \ |
| WRITE_VCBUS_REG( \ |
| VD1_BLEND_SRC_CTRL + \ |
| vd_layer[0].misc_reg_offt, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[0].vd_afbc_reg.afbc_enable, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[0].vd_mif_reg.vd_if0_gen_reg, \ |
| 0); \ |
| if (!legacy_vpp) \ |
| WRITE_VCBUS_REG( \ |
| VD2_BLEND_SRC_CTRL + \ |
| vd_layer[1].misc_reg_offt, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[1].vd_afbc_reg.afbc_enable, 0); \ |
| WRITE_VCBUS_REG( \ |
| vd_layer[1].vd_mif_reg.vd_if0_gen_reg, 0); \ |
| pr_info("VIDEO: disable_video_all_layer_nodelay()\n"); \ |
| } while (0) |
| |
| void dv_mem_power_off(enum vpu_mod_e mode) |
| { |
| unsigned long flags; |
| unsigned int dv_flag; |
| |
| if (mode == VPU_DOLBY0) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY0; |
| else if (mode == VPU_DOLBY1A) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1A; |
| else if (mode == VPU_DOLBY1B) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1B; |
| else if (mode == VPU_DOLBY2) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY2; |
| else if (mode == VPU_DOLBY_CORE3) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY_CORE3; |
| else if (mode == VPU_PRIME_DOLBY_RAM) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_PRIME_DOLBY; |
| else |
| return; |
| spin_lock_irqsave(&delay_work_lock, flags); |
| vpu_delay_work_flag |= dv_flag; |
| dv_mem_power_off_count = DV_MEM_POWEROFF_DELAY; |
| spin_unlock_irqrestore(&delay_work_lock, flags); |
| } |
| EXPORT_SYMBOL(dv_mem_power_off); |
| |
| void dv_mem_power_on(enum vpu_mod_e mode) |
| { |
| unsigned long flags; |
| unsigned int dv_flag; |
| |
| if (mode == VPU_DOLBY0) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY0; |
| else if (mode == VPU_DOLBY1A) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1A; |
| else if (mode == VPU_DOLBY1B) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1B; |
| else if (mode == VPU_DOLBY2) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY2; |
| else if (mode == VPU_DOLBY_CORE3) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY_CORE3; |
| else if (mode == VPU_PRIME_DOLBY_RAM) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_PRIME_DOLBY; |
| else |
| return; |
| |
| spin_lock_irqsave(&delay_work_lock, flags); |
| vpu_delay_work_flag &= ~dv_flag; |
| spin_unlock_irqrestore(&delay_work_lock, flags); |
| switch_vpu_mem_pd_vmod(mode, VPU_MEM_POWER_ON); |
| } |
| EXPORT_SYMBOL(dv_mem_power_on); |
| |
| int get_dv_mem_power_flag(enum vpu_mod_e mode) |
| { |
| unsigned long flags; |
| unsigned int dv_flag; |
| int ret = VPU_MEM_POWER_ON; |
| |
| if (mode == VPU_DOLBY0) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY0; |
| else if (mode == VPU_DOLBY1A) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1A; |
| else if (mode == VPU_DOLBY1B) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1B; |
| else if (mode == VPU_DOLBY2) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY2; |
| else if (mode == VPU_DOLBY_CORE3) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_DOLBY_CORE3; |
| else if (mode == VPU_PRIME_DOLBY_RAM) |
| dv_flag = VPU_DELAYWORK_MEM_POWER_OFF_PRIME_DOLBY; |
| else |
| return -1; |
| |
| spin_lock_irqsave(&delay_work_lock, flags); |
| if (vpu_delay_work_flag & dv_flag) |
| ret = VPU_MEM_POWER_DOWN; |
| spin_unlock_irqrestore(&delay_work_lock, flags); |
| return ret; |
| } |
| EXPORT_SYMBOL(get_dv_mem_power_flag); |
| |
| /*********************************************************/ |
| static struct vframe_pic_mode_s gpic_info[MAX_VD_LAYERS]; |
| static u32 reference_zorder = 128; |
| static u32 vpp_hold_line = 8; |
| |
| static const enum f2v_vphase_type_e vpp_phase_table[4][3] = { |
| {F2V_P2IT, F2V_P2IB, F2V_P2P}, /* VIDTYPE_PROGRESSIVE */ |
| {F2V_IT2IT, F2V_IT2IB, F2V_IT2P}, /* VIDTYPE_INTERLACE_TOP */ |
| {F2V_P2IT, F2V_P2IB, F2V_P2P}, |
| {F2V_IB2IT, F2V_IB2IB, F2V_IB2P} /* VIDTYPE_INTERLACE_BOTTOM */ |
| }; |
| |
| static const u8 skip_tab[6] = { 0x24, 0x04, 0x68, 0x48, 0x28, 0x08 }; |
| |
| static bool video_mute_on; |
| /* 0: off, 1: vpp mute 2:dv mute */ |
| static int video_mute_status; |
| |
| /* if vf width >= threshold, disable SR dynamically */ |
| static u32 disable_sr_threshold = 2560; |
| |
| /********************************************************* |
| * Utils APIs |
| *********************************************************/ |
| #ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| bool is_dolby_vision_enable(void) |
| { |
| return false; |
| } |
| |
| bool is_dolby_vision_on(void) |
| { |
| return false; |
| } |
| |
| bool is_dolby_vision_stb_mode(void) |
| { |
| return false; |
| } |
| |
| bool for_dolby_vision_certification(void) |
| { |
| return false; |
| } |
| #endif |
| |
| bool is_dovi_tv_on(void) |
| { |
| #ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| return false; |
| #else |
| return ((is_meson_txlx_package_962X() || is_meson_tm2_cpu()) && |
| !is_dolby_vision_stb_mode() && is_dolby_vision_on()); |
| #endif |
| } |
| |
| struct video_dev_s *get_video_cur_dev(void) |
| { |
| return cur_dev; |
| } |
| |
| u32 get_video_enabled(void) |
| { |
| return vd_layer[0].enabled && vd_layer[0].global_output; |
| } |
| EXPORT_SYMBOL(get_video_enabled); |
| |
| u32 get_videopip_enabled(void) |
| { |
| return vd_layer[1].enabled && vd_layer[1].global_output; |
| } |
| EXPORT_SYMBOL(get_videopip_enabled); |
| |
| void set_video_enabled(u32 value, u32 index) |
| { |
| u32 disable_video = value ? 0 : 1; |
| |
| if (index >= MAX_VD_LAYER) |
| return; |
| vd_layer[index].global_output = value; |
| if (index == 0) |
| _video_set_disable(disable_video); |
| else |
| _videopip_set_disable(disable_video); |
| } |
| EXPORT_SYMBOL(set_video_enabled); |
| |
| bool get_disable_video_flag(enum vd_path_e vd_path) |
| { |
| if (vd_path == VD1_PATH) |
| return vd_layer[0].disable_video == VIDEO_DISABLE_NORMAL; |
| else if (vd_path == VD2_PATH) |
| return vd_layer[1].disable_video == VIDEO_DISABLE_NORMAL; |
| |
| return false; |
| } |
| EXPORT_SYMBOL(get_disable_video_flag); |
| |
| bool is_di_on(void) |
| { |
| bool ret = false; |
| |
| if (DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) |
| ret = true; |
| return ret; |
| } |
| |
| bool is_di_post_on(void) |
| { |
| bool ret = false; |
| |
| if (DI_POST_REG_RD(DI_POST_CTRL) & 0x100) |
| ret = true; |
| return ret; |
| } |
| |
| bool is_di_post_link_on(void) |
| { |
| bool ret = false; |
| |
| if (DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) |
| ret = true; |
| return ret; |
| } |
| |
| bool is_di_post_mode(struct vframe_s *vf) |
| { |
| bool ret = false; |
| |
| if (vf && (vf->type & VIDTYPE_PRE_INTERLACE) && |
| !(vf->type & VIDTYPE_DI_PW)) |
| ret = true; |
| return ret; |
| } |
| |
| bool is_afbc_enabled(u8 layer_id) |
| { |
| struct video_layer_s *layer = NULL; |
| u32 value; |
| |
| if (layer_id >= MAX_VD_LAYER) |
| return -1; |
| |
| layer = &vd_layer[layer_id]; |
| value = READ_VCBUS_REG(layer->vd_afbc_reg.afbc_enable); |
| return (value & 0x100) ? true : false; |
| } |
| |
| bool is_local_vf(struct vframe_s *vf) |
| { |
| if (vf && |
| ((vf == &vf_local) || |
| (vf == &vf_local2) || |
| (vf == &local_pip))) |
| return true; |
| |
| /* FIXEME: remove gvideo_recv */ |
| if (vf && gvideo_recv[0] && |
| (vf == &gvideo_recv[0]->local_buf)) |
| return true; |
| if (vf && gvideo_recv[1] && |
| (vf == &gvideo_recv[1]->local_buf)) |
| return true; |
| return false; |
| } |
| |
| static u32 is_crop_left_odd(struct vpp_frame_par_s *frame_par) |
| { |
| int crop_left_odd; |
| |
| /* odd, not even aligned*/ |
| if (frame_par->VPP_hd_start_lines_ & 0x01) |
| crop_left_odd = 1; |
| else |
| crop_left_odd = 0; |
| return crop_left_odd; |
| } |
| |
| /********************************************************* |
| * vd HW APIs |
| *********************************************************/ |
| void safe_switch_videolayer(u8 layer_id, bool on, bool async) |
| { |
| if (layer_id == 0xff) |
| pr_debug("VID: VD all %s with async %s\n", |
| on ? "on" : "off", |
| async ? "true" : "false"); |
| else |
| pr_debug("VID: VD%d %s with async %s\n", |
| layer_id, |
| on ? "on" : "off", |
| async ? "true" : "false"); |
| |
| if (layer_id == 0) { |
| if (on) |
| enable_video_layer(); |
| else |
| disable_video_layer(async); |
| } |
| |
| if (layer_id == 1) { |
| if (on) |
| enable_video_layer2(); |
| else |
| disable_video_layer2(async); |
| } |
| |
| if (layer_id == 0xff) { |
| if (on) { |
| enable_video_layer(); |
| enable_video_layer2(); |
| } else if (async) { |
| disable_video_layer(async); |
| disable_video_layer2(async); |
| } else { |
| disable_video_all_layer_nodelay(); |
| } |
| } |
| } |
| |
| static void vd1_path_select( |
| struct video_layer_s *layer, |
| bool afbc, bool di_afbc, bool di_post) |
| { |
| u32 misc_off = layer->misc_reg_offt; |
| |
| if (!legacy_vpp) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VD1_AFBCD0_MISC_CTRL, |
| /* go field sel */ |
| (0 << 20) | |
| /* linebuffer en */ |
| (0 << 16) | |
| /* vd1 -> dolby -> vpp top */ |
| (0 << 14) | |
| /* axi sel: vd1 mif or afbc */ |
| (((afbc || di_afbc) ? 1 : 0) << 12) | |
| /* data sel: vd1 & afbc0 (not osd4) */ |
| (0 << 11) | |
| /* data sel: afbc0 or vd1 */ |
| ((afbc ? 1 : 0) << 10) | |
| /* afbc0 to vd1 (not di) */ |
| ((di_afbc ? 1 : 0) << 9) | |
| /* vd1 mif to vpp (not di) */ |
| (0 << 8) | |
| /* afbc0 gclk ctrl */ |
| (0 << 0), |
| 0, 22); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) |
| VSYNC_WR_MPEG_REG_BITS( |
| VD1_AFBCD0_MISC_CTRL, |
| /* Vd1_afbc0_mem_sel */ |
| (afbc ? 1 : 0), |
| 22, 1); |
| if (di_post) { |
| /* check di_vpp_out_en bit */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VD1_AFBCD0_MISC_CTRL, |
| /* vd1 mif to di */ |
| 1, |
| 8, 2); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD1_AFBCD0_MISC_CTRL, |
| /* go field select di post */ |
| 1, |
| 20, 2); |
| } |
| } else { |
| if (!di_post) |
| VSYNC_WR_MPEG_REG_BITS( |
| VIU_MISC_CTRL0 + misc_off, |
| 0, 16, 3); |
| VSYNC_WR_MPEG_REG_BITS( |
| VIU_MISC_CTRL0 + misc_off, |
| (afbc ? 1 : 0), 20, 1); |
| } |
| } |
| |
| static void vd2_path_select( |
| struct video_layer_s *layer, |
| bool afbc, bool di_afbc) |
| { |
| u32 misc_off = layer->misc_reg_offt; |
| |
| if (!legacy_vpp) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_AFBCD1_MISC_CTRL, |
| /* go field sel */ |
| (0 << 20) | |
| /* linebuffer en */ |
| (0 << 16) | |
| /* TODO: vd2 -> dolby -> vpp top ?? */ |
| (0 << 14) | |
| /* axi sel: vd2 mif */ |
| (((afbc || di_afbc) ? 1 : 0) << 12) | |
| /* data sel: vd2 & afbc1 (not osd4) */ |
| (0 << 11) | |
| /* data sel: afbc1 */ |
| ((afbc ? 1 : 0) << 10) | |
| /* afbc1 to vd2 (not di) */ |
| ((di_afbc ? 1 : 0) << 9) | |
| /* vd2 mif to vpp (not di) */ |
| (0 << 8) | |
| /* afbc1 gclk ctrl */ |
| (0 << 0), |
| 0, 22); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_AFBCD1_MISC_CTRL, |
| /* Vd2_afbc0_mem_sel */ |
| (afbc ? 1 : 0), |
| 22, 1); |
| } else { |
| VSYNC_WR_MPEG_REG_BITS( |
| VIU_MISC_CTRL1 + misc_off, |
| (afbc ? 2 : 0), 0, 2); |
| } |
| } |
| |
| static void vd1_set_dcu( |
| struct video_layer_s *layer, |
| struct vpp_frame_par_s *frame_par, |
| struct vframe_s *vf) |
| { |
| u32 r; |
| u32 vphase, vini_phase, vformatter, vrepeat, hphase = 0; |
| u32 hformatter; |
| u32 pat, loop; |
| static const u32 vpat[MAX_VSKIP_COUNT + 1] = { |
| 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; |
| u32 u, v; |
| u32 type, bit_mode = 0, canvas_w; |
| bool is_mvc = false; |
| u8 burst_len = 1; |
| struct hw_vd_reg_s *vd_mif_reg = &layer->vd_mif_reg; |
| struct hw_vd_reg_s *vd2_mif_reg = &vd_layer[1].vd_mif_reg; |
| struct hw_afbc_reg_s *vd_afbc_reg = &layer->vd_afbc_reg; |
| bool di_post = false; |
| |
| if (!vf) { |
| pr_info("vd1_set_dcu vf NULL, return\n"); |
| return; |
| } |
| |
| type = vf->type; |
| if (type & VIDTYPE_MVC) |
| is_mvc = true; |
| |
| pr_debug("%s for vd%d %p, type:0x%x\n", |
| __func__, layer->layer_id, vf, type); |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (is_di_post_mode(vf) && is_di_post_on()) |
| di_post = true; |
| #endif |
| |
| if (frame_par->nocomp) |
| type &= ~VIDTYPE_COMPRESS; |
| |
| if (type & VIDTYPE_COMPRESS) { |
| if (!legacy_vpp || is_meson_txlx_cpu()) |
| burst_len = 2; |
| r = (3 << 24) | |
| (vpp_hold_line << 16) | |
| (burst_len << 14) | /* burst1 */ |
| (vf->bitdepth & BITDEPTH_MASK); |
| |
| if (frame_par->hscale_skip_count) |
| r |= 0x33; |
| if (frame_par->vscale_skip_count) |
| r |= 0xcc; |
| |
| /* FIXME: don't use glayer_info[0].reverse */ |
| if (glayer_info[0].reverse) |
| r |= (1 << 26) | (1 << 27); |
| else if (glayer_info[0].mirror == H_MIRROR) |
| r |= (1 << 26) | (0 << 27); |
| else if (glayer_info[0].mirror == V_MIRROR) |
| r |= (0 << 26) | (1 << 27); |
| |
| if (vf->bitdepth & BITDEPTH_SAVING_MODE) |
| r |= (1 << 28); /* mem_saving_mode */ |
| if (type & VIDTYPE_SCATTER) |
| r |= (1 << 29); |
| VSYNC_WR_MPEG_REG(vd_afbc_reg->afbc_mode, r); |
| |
| r = 0x1700; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if (vf && (vf->source_type |
| != VFRAME_SOURCE_TYPE_HDMI)) |
| r |= (1 << 19); /* dos_uncomp */ |
| |
| if (type & VIDTYPE_COMB_MODE) |
| r |= (1 << 20); |
| } |
| VSYNC_WR_MPEG_REG(vd_afbc_reg->afbc_enable, r); |
| |
| r = 0x100; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if ((type & VIDTYPE_VIU_444) || |
| (type & VIDTYPE_RGB_444)) |
| r |= 0; |
| else if (type & VIDTYPE_VIU_422) |
| r |= (1 << 12); |
| else |
| r |= (2 << 12); |
| } |
| VSYNC_WR_MPEG_REG(vd_afbc_reg->afbc_conv_ctrl, r); |
| |
| u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; |
| v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_dec_def_color, |
| 0x3FF00000 | /*Y,bit20+*/ |
| 0x80 << (u + 10) | |
| 0x80 << v); |
| /* chroma formatter */ |
| r = HFORMATTER_REPEAT | |
| HFORMATTER_YC_RATIO_2_1 | |
| HFORMATTER_EN | |
| (0x8 << VFORMATTER_PHASE_BIT) | |
| VFORMATTER_EN; |
| if (is_dovi_tv_on()) |
| r |= VFORMATTER_ALWAYS_RPT | |
| (0x0 << VFORMATTER_INIPHASE_BIT); |
| else |
| r |= VFORMATTER_RPTLINE0_EN | |
| (0xc << VFORMATTER_INIPHASE_BIT); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if ((type & VIDTYPE_VIU_444) || |
| (type & VIDTYPE_RGB_444)) { |
| r &= ~HFORMATTER_EN; |
| r &= ~VFORMATTER_EN; |
| r &= ~HFORMATTER_YC_RATIO_2_1; |
| } else if (type & VIDTYPE_VIU_422) { |
| r &= ~VFORMATTER_EN; |
| } |
| } |
| VSYNC_WR_MPEG_REG(vd_afbc_reg->afbc_vd_cfmt_ctrl, r); |
| |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if (type & VIDTYPE_COMPRESS_LOSS) |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbcdec_iquant_enable, |
| ((1 << 11) | |
| (1 << 10) | |
| (1 << 4) | |
| (1 << 0))); |
| else |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbcdec_iquant_enable, 0); |
| } |
| vd1_path_select(layer, true, false, di_post); |
| if (is_mvc) |
| vd2_path_select(layer, true, false); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_gen_reg, 0); |
| return; |
| } |
| |
| /* vd mif burst len is 2 as default */ |
| burst_len = 2; |
| if (vf->canvas0Addr != (u32)-1) |
| canvas_w = canvas_get_width( |
| vf->canvas0Addr & 0xff); |
| else |
| canvas_w = vf->canvas0_config[0].width; |
| |
| if (canvas_w % 32) |
| burst_len = 0; |
| else if (canvas_w % 64) |
| burst_len = 1; |
| |
| if ((vf->bitdepth & BITDEPTH_Y10) && |
| !frame_par->nocomp) { |
| if ((vf->type & VIDTYPE_VIU_444) || |
| (vf->type & VIDTYPE_RGB_444)) { |
| bit_mode = 2; |
| } else { |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| bit_mode = 3; |
| else |
| bit_mode = 1; |
| } |
| } else { |
| bit_mode = 0; |
| } |
| if (!legacy_vpp) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| (bit_mode & 0x3), 8, 2); |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| (burst_len & 0x3), 1, 2); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| 0, 0, 1); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| 1, 0, 1); |
| if (is_mvc) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| (bit_mode & 0x3), 8, 2); |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| (burst_len & 0x3), 1, 2); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 0, 0, 1); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 1, 0, 1); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| (bit_mode & 0x3), 8, 2); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| 0, 0, 1); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg3, |
| 1, 0, 1); |
| |
| if (is_mvc) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| (bit_mode & 0x3), 8, 2); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 0, 0, 1); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 1, 0, 1); |
| |
| } |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (is_di_post_mode(vf)) { |
| DI_POST_WR_REG_BITS( |
| DI_IF1_GEN_REG3, |
| (bit_mode & 0x3), 8, 2); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) |
| DI_POST_WR_REG_BITS( |
| DI_IF2_GEN_REG3, |
| (bit_mode & 0x3), 8, 2); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) |
| DI_POST_WR_REG_BITS( |
| DI_IF0_GEN_REG3, |
| (bit_mode & 0x3), 8, 2); |
| } |
| #endif |
| if (glayer_info[0].need_no_compress || |
| (vf->type & VIDTYPE_PRE_DI_AFBC)) { |
| vd1_path_select(layer, false, true, di_post); |
| } else { |
| vd1_path_select(layer, false, false, di_post); |
| if (is_mvc) |
| vd2_path_select(layer, false, false); |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_enable, 0); |
| } |
| |
| r = (3 << VDIF_URGENT_BIT) | |
| (vpp_hold_line << VDIF_HOLD_LINES_BIT) | |
| VDIF_FORMAT_SPLIT | |
| VDIF_CHRO_RPT_LAST | VDIF_ENABLE; |
| /* | VDIF_RESET_ON_GO_FIELD;*/ |
| if (layer->global_debug & DEBUG_FLAG_GOFIELD_MANUL) |
| r |= 1 << 7; /*for manul triggle gofiled.*/ |
| |
| if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0) { |
| r |= VDIF_SEPARATE_EN; |
| } else { |
| if (type & VIDTYPE_VIU_422) |
| r |= VDIF_FORMAT_422; |
| else |
| r |= VDIF_FORMAT_RGB888_YUV444 | |
| VDIF_DEMUX_MODE_RGB_444; |
| } |
| |
| if (frame_par->hscale_skip_count) { |
| if ((type & VIDTYPE_VIU_444) || (type & VIDTYPE_RGB_444)) |
| r |= VDIF_LUMA_HZ_AVG; |
| else |
| r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; |
| } |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| r |= (1 << 4); |
| |
| /*enable go field reset default according to vlsi*/ |
| r |= VDIF_RESET_ON_GO_FIELD; |
| VSYNC_WR_MPEG_REG(vd_mif_reg->vd_if0_gen_reg, r); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_gen_reg, r); |
| |
| if (type & VIDTYPE_VIU_NV21) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 1, 0, 2); |
| else if (type & VIDTYPE_VIU_NV12) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 2, 0, 2); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 0, 0, 2); |
| |
| /* FIXME: don't use glayer_info[0].reverse */ |
| if (glayer_info[0].reverse) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 0xf, 2, 4); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, 0xf, 2, 4); |
| } else if (glayer_info[0].mirror == H_MIRROR) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 0x5, 2, 4); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, 0x5, 2, 4); |
| } else if (glayer_info[0].mirror == V_MIRROR) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 0xa, 2, 4); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, 0xa, 2, 4); |
| } else { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->vd_if0_gen_reg2, 0, 2, 4); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, 0, 2, 4); |
| } |
| |
| /* chroma formatter */ |
| if ((type & VIDTYPE_VIU_444) || |
| (type & VIDTYPE_RGB_444)) { |
| r = HFORMATTER_YC_RATIO_1_1; |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->viu_vd_fmt_ctrl, r); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->viu_vd_fmt_ctrl, r); |
| } else { |
| /* TODO: if always use HFORMATTER_REPEAT */ |
| if (is_crop_left_odd(frame_par)) { |
| if ((type & VIDTYPE_VIU_NV21) || |
| (type & VIDTYPE_VIU_NV12) || |
| (type & VIDTYPE_VIU_422)) |
| hphase = 0x8 << HFORMATTER_PHASE_BIT; |
| } |
| if ((frame_par->hscale_skip_count) && |
| (type & VIDTYPE_VIU_422)) |
| hformatter = |
| (HFORMATTER_YC_RATIO_2_1 | |
| hphase); |
| else |
| hformatter = |
| (HFORMATTER_YC_RATIO_2_1 | |
| hphase | |
| HFORMATTER_EN); |
| if (is_dolby_vision_on()) |
| hformatter |= HFORMATTER_REPEAT; |
| vrepeat = VFORMATTER_RPTLINE0_EN; |
| vini_phase = (0xc << VFORMATTER_INIPHASE_BIT); |
| if (type & VIDTYPE_VIU_422) { |
| vformatter = 0; |
| vphase = (0x10 << VFORMATTER_PHASE_BIT); |
| } else { |
| /*vlsi suggest only for yuv420 vformatter should be 1*/ |
| vformatter = VFORMATTER_EN; |
| vphase = (0x08 << VFORMATTER_PHASE_BIT); |
| } |
| if (is_dovi_tv_on()) { |
| /* dolby vision tv mode */ |
| vini_phase = (0 << VFORMATTER_INIPHASE_BIT); |
| /* TODO: check the vrepeat */ |
| if (type & VIDTYPE_VIU_422) |
| vrepeat = VFORMATTER_RPTLINE0_EN; |
| else |
| vrepeat = VFORMATTER_ALWAYS_RPT; |
| } else if (is_mvc) { |
| /* mvc source */ |
| vini_phase = (0xe << VFORMATTER_INIPHASE_BIT); |
| } else if (type & VIDTYPE_TYPEMASK) { |
| /* interlace source */ |
| if ((type & VIDTYPE_TYPEMASK) == |
| VIDTYPE_INTERLACE_TOP) |
| vini_phase = |
| (0xe << VFORMATTER_INIPHASE_BIT); |
| else |
| vini_phase = |
| (0xa << VFORMATTER_INIPHASE_BIT); |
| } |
| vformatter |= (vphase | vini_phase | vrepeat); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->viu_vd_fmt_ctrl, |
| hformatter | vformatter); |
| |
| if (is_mvc) { |
| vini_phase = (0xa << VFORMATTER_INIPHASE_BIT); |
| vformatter = (vphase | vini_phase |
| | vrepeat | VFORMATTER_EN); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->viu_vd_fmt_ctrl, |
| hformatter | vformatter); |
| } |
| } |
| |
| if (is_meson_txlx_cpu() || |
| cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd_mif_reg->viu_vd_fmt_ctrl, |
| 1, 29, 1); |
| |
| /* LOOP/SKIP pattern */ |
| pat = vpat[frame_par->vscale_skip_count]; |
| |
| if (type & VIDTYPE_VIU_FIELD) { |
| loop = 0; |
| |
| if (type & VIDTYPE_INTERLACE) |
| pat = vpat[frame_par->vscale_skip_count >> 1]; |
| } else if (is_mvc) { |
| loop = 0x11; |
| if (framepacking_support) |
| pat = 0; |
| else |
| pat = 0x80; |
| } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { |
| loop = 0x11; |
| pat <<= 4; |
| } else { |
| loop = 0; |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_rpt_loop, |
| (loop << VDIF_CHROMA_LOOP1_BIT) | |
| (loop << VDIF_LUMA_LOOP1_BIT) | |
| (loop << VDIF_CHROMA_LOOP0_BIT) | |
| (loop << VDIF_LUMA_LOOP0_BIT)); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_rpt_loop, |
| (loop << VDIF_CHROMA_LOOP1_BIT) | |
| (loop << VDIF_LUMA_LOOP1_BIT) | |
| (loop << VDIF_CHROMA_LOOP0_BIT) | |
| (loop << VDIF_LUMA_LOOP0_BIT)); |
| |
| VSYNC_WR_MPEG_REG(vd_mif_reg->vd_if0_luma0_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG(vd_mif_reg->vd_if0_chroma0_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG(vd_mif_reg->vd_if0_luma1_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG(vd_mif_reg->vd_if0_chroma1_rpt_pat, pat); |
| |
| if (is_mvc) { |
| if (framepacking_support) |
| pat = 0; |
| else |
| pat = 0x88; |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma0_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma0_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma1_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma1_rpt_pat, pat); |
| } |
| |
| /* picture 0/1 control */ |
| if ((((type & VIDTYPE_INTERLACE) == 0) && |
| ((type & VIDTYPE_VIU_FIELD) == 0) && |
| ((type & VIDTYPE_MVC) == 0)) || |
| (frame_par->vpp_2pic_mode & 0x3)) { |
| /* progressive frame in two pictures */ |
| r = ((2 << 26) | /* two pic mode */ |
| (2 << 24) | /* use own last line */ |
| 0x01); /* loop pattern */ |
| if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) |
| r |= (1 << 8); /* use pic1 first*/ |
| else |
| r |= (2 << 8); /* use pic0 first */ |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_psel, r); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_psel, r); |
| } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { |
| /*FA LR/TB output , do nothing*/ |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_psel, 0); |
| if (is_mvc) { |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_psel, 0); |
| } |
| } |
| } |
| |
| static void vd2_set_dcu( |
| struct video_layer_s *layer, |
| struct vpp_frame_par_s *frame_par, |
| struct vframe_s *vf) |
| { |
| u32 r; |
| u32 vphase, vini_phase, vformatter, vrepeat, hphase = 0; |
| u32 hformatter; |
| u32 pat, loop; |
| static const u32 vpat[MAX_VSKIP_COUNT + 1] = { |
| 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; |
| u32 u, v; |
| u32 type, bit_mode = 0, canvas_w; |
| bool is_mvc = false; |
| u8 burst_len = 1; |
| struct hw_vd_reg_s *vd2_mif_reg = &layer->vd_mif_reg; |
| struct hw_afbc_reg_s *vd2_afbc_reg = &layer->vd_afbc_reg; |
| |
| if (!vf) { |
| pr_err("vd2_set_dcu vf is NULL\n"); |
| return; |
| } |
| |
| type = vf->type; |
| if (type & VIDTYPE_MVC) |
| is_mvc = true; |
| pr_debug("%s for vd%d %p, type:0x%x\n", |
| __func__, layer->layer_id, vf, type); |
| |
| if (frame_par->nocomp) |
| type &= ~VIDTYPE_COMPRESS; |
| |
| if (type & VIDTYPE_COMPRESS) { |
| if (!legacy_vpp || is_meson_txlx_cpu()) |
| burst_len = 2; |
| r = (3 << 24) | |
| (vpp_hold_line << 16) | |
| (burst_len << 14) | /* burst1 */ |
| (vf->bitdepth & BITDEPTH_MASK); |
| |
| if (frame_par->hscale_skip_count) |
| r |= 0x33; |
| if (frame_par->vscale_skip_count) |
| r |= 0xcc; |
| |
| /* FIXME: don't use glayer_info[1].reverse */ |
| if (glayer_info[1].reverse) |
| r |= (1 << 26) | (1 << 27); |
| else if (glayer_info[1].mirror == H_MIRROR) |
| r |= (1 << 26) | (0 << 27); |
| else if (glayer_info[1].mirror == V_MIRROR) |
| r |= (0 << 26) | (1 << 27); |
| |
| |
| if (vf->bitdepth & BITDEPTH_SAVING_MODE) |
| r |= (1 << 28); /* mem_saving_mode */ |
| if (type & VIDTYPE_SCATTER) |
| r |= (1 << 29); |
| VSYNC_WR_MPEG_REG(vd2_afbc_reg->afbc_mode, r); |
| |
| r = 0x1700; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if (vf && (vf->source_type |
| != VFRAME_SOURCE_TYPE_HDMI)) |
| r |= (1 << 19); /* dos_uncomp */ |
| } |
| VSYNC_WR_MPEG_REG(vd2_afbc_reg->afbc_enable, r); |
| |
| r = 0x100; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if ((type & VIDTYPE_VIU_444) || |
| (type & VIDTYPE_RGB_444)) |
| r |= 0; |
| else if (type & VIDTYPE_VIU_422) |
| r |= (1 << 12); |
| else |
| r |= (2 << 12); |
| } |
| VSYNC_WR_MPEG_REG(vd2_afbc_reg->afbc_conv_ctrl, r); |
| |
| u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; |
| v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_dec_def_color, |
| 0x3FF00000 | /*Y,bit20+*/ |
| 0x80 << (u + 10) | |
| 0x80 << v); |
| |
| /* chroma formatter */ |
| r = HFORMATTER_YC_RATIO_2_1 | |
| HFORMATTER_EN | |
| (0x8 << VFORMATTER_PHASE_BIT) | |
| VFORMATTER_EN; |
| if (is_dovi_tv_on()) |
| r |= HFORMATTER_REPEAT | |
| VFORMATTER_ALWAYS_RPT | |
| (0x0 << VFORMATTER_INIPHASE_BIT); |
| else if (is_dolby_vision_on()) /* stb case */ |
| r |= HFORMATTER_REPEAT | |
| VFORMATTER_RPTLINE0_EN | |
| (0xc << VFORMATTER_INIPHASE_BIT); |
| else |
| r |= HFORMATTER_RRT_PIXEL0 | |
| VFORMATTER_RPTLINE0_EN | |
| (0 << VFORMATTER_INIPHASE_BIT); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if ((type & VIDTYPE_VIU_444) || |
| (type & VIDTYPE_RGB_444)) { |
| r &= ~HFORMATTER_EN; |
| r &= ~VFORMATTER_EN; |
| r &= ~HFORMATTER_YC_RATIO_2_1; |
| } else if (type & VIDTYPE_VIU_422) { |
| r &= ~VFORMATTER_EN; |
| } |
| } |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_vd_cfmt_ctrl, r); |
| |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if (type & VIDTYPE_COMPRESS_LOSS) |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbcdec_iquant_enable, |
| ((1 << 11) | |
| (1 << 10) | |
| (1 << 4) | |
| (1 << 0))); |
| else |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbcdec_iquant_enable, 0); |
| } |
| |
| vd2_path_select(layer, true, false); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_gen_reg, 0); |
| return; |
| } |
| |
| /* vd mif burst len is 2 as default */ |
| burst_len = 2; |
| if (vf->canvas0Addr != (u32)-1) |
| canvas_w = canvas_get_width( |
| vf->canvas0Addr & 0xff); |
| else |
| canvas_w = vf->canvas0_config[0].width; |
| |
| if (canvas_w % 32) |
| burst_len = 0; |
| else if (canvas_w % 64) |
| burst_len = 1; |
| |
| if ((vf->bitdepth & BITDEPTH_Y10) && |
| !frame_par->nocomp) { |
| if ((vf->type & VIDTYPE_VIU_444) || |
| (vf->type & VIDTYPE_RGB_444)) { |
| bit_mode = 2; |
| } else { |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| bit_mode = 3; |
| else |
| bit_mode = 1; |
| } |
| } else { |
| bit_mode = 0; |
| } |
| |
| vd2_path_select(layer, false, false); |
| if (!legacy_vpp) { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| (bit_mode & 0x3), 8, 2); |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| (burst_len & 0x3), 1, 2); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 0, 0, 1); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 1, 0, 1); |
| } else { |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| (bit_mode & 0x3), 8, 2); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 0, 0, 1); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg3, |
| 1, 0, 1); |
| } |
| if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1)) |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_enable, 0); |
| |
| r = (3 << VDIF_URGENT_BIT) | |
| (vpp_hold_line << VDIF_HOLD_LINES_BIT) | |
| VDIF_FORMAT_SPLIT | |
| VDIF_CHRO_RPT_LAST | VDIF_ENABLE; |
| /* | VDIF_RESET_ON_GO_FIELD;*/ |
| if (layer->global_debug & DEBUG_FLAG_GOFIELD_MANUL) |
| r |= 1 << 7; /*for manul triggle gofiled.*/ |
| |
| if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0) { |
| r |= VDIF_SEPARATE_EN; |
| } else { |
| if (type & VIDTYPE_VIU_422) |
| r |= VDIF_FORMAT_422; |
| else |
| r |= VDIF_FORMAT_RGB888_YUV444 | |
| VDIF_DEMUX_MODE_RGB_444; |
| } |
| |
| if (frame_par->hscale_skip_count) { |
| if ((type & VIDTYPE_VIU_444) || (type & VIDTYPE_RGB_444)) |
| r |= VDIF_LUMA_HZ_AVG; |
| else |
| r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; |
| } |
| |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| r |= (1 << 4); |
| |
| VSYNC_WR_MPEG_REG(vd2_mif_reg->vd_if0_gen_reg, r); |
| |
| if (type & VIDTYPE_VIU_NV21) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 1, 0, 2); |
| else if (type & VIDTYPE_VIU_NV12) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 2, 0, 2); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 0, 0, 2); |
| |
| /* FIXME: don't use glayer_info[1].reverse */ |
| if (glayer_info[1].reverse) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 0xf, 2, 4); |
| else if (glayer_info[1].mirror == H_MIRROR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 0x5, 2, 4); |
| else if (glayer_info[1].mirror == V_MIRROR) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 0xa, 2, 4); |
| else |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->vd_if0_gen_reg2, |
| 0, 2, 4); |
| |
| /* chroma formatter */ |
| if ((type & VIDTYPE_VIU_444) || |
| (type & VIDTYPE_RGB_444)) { |
| r = HFORMATTER_YC_RATIO_1_1; |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->viu_vd_fmt_ctrl, r); |
| } else { |
| /* TODO: if always use HFORMATTER_REPEAT */ |
| if (is_crop_left_odd(frame_par)) { |
| if ((type & VIDTYPE_VIU_NV21) || |
| (type & VIDTYPE_VIU_NV12) || |
| (type & VIDTYPE_VIU_422)) |
| hphase = 0x8 << HFORMATTER_PHASE_BIT; |
| } |
| if ((frame_par->hscale_skip_count) && |
| (type & VIDTYPE_VIU_422)) |
| hformatter = |
| (HFORMATTER_YC_RATIO_2_1 | |
| hphase); |
| else |
| hformatter = |
| (HFORMATTER_YC_RATIO_2_1 | |
| hphase | |
| HFORMATTER_EN); |
| if (is_dolby_vision_on()) |
| hformatter |= HFORMATTER_REPEAT; |
| vrepeat = VFORMATTER_RPTLINE0_EN; |
| vini_phase = (0xc << VFORMATTER_INIPHASE_BIT); |
| if (type & VIDTYPE_VIU_422) { |
| vformatter = 0; |
| vphase = (0x10 << VFORMATTER_PHASE_BIT); |
| } else { |
| /*vlsi suggest only for yuv420 vformatter should be 1*/ |
| vformatter = VFORMATTER_EN; |
| vphase = (0x08 << VFORMATTER_PHASE_BIT); |
| } |
| if (is_dovi_tv_on()) { |
| /* dolby vision tv mode */ |
| vini_phase = (0 << VFORMATTER_INIPHASE_BIT); |
| /* TODO: check the vrepeat */ |
| if (type & VIDTYPE_VIU_422) |
| vrepeat = VFORMATTER_RPTLINE0_EN; |
| else |
| vrepeat = VFORMATTER_ALWAYS_RPT; |
| } else if (is_mvc) { |
| /* mvc source */ |
| /* vini_phase = (0xe << VFORMATTER_INIPHASE_BIT); */ |
| vini_phase = (0xa << VFORMATTER_INIPHASE_BIT); |
| } else if (type & VIDTYPE_TYPEMASK) { |
| /* interlace source */ |
| if ((type & VIDTYPE_TYPEMASK) == |
| VIDTYPE_INTERLACE_TOP) |
| vini_phase = |
| (0xe << VFORMATTER_INIPHASE_BIT); |
| else |
| vini_phase = |
| (0xa << VFORMATTER_INIPHASE_BIT); |
| } |
| vformatter |= (vphase | vini_phase | vrepeat); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->viu_vd_fmt_ctrl, |
| hformatter | vformatter); |
| } |
| if (is_meson_txlx_cpu() || |
| cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) |
| VSYNC_WR_MPEG_REG_BITS( |
| vd2_mif_reg->viu_vd_fmt_ctrl, |
| 1, 29, 1); |
| /* LOOP/SKIP pattern */ |
| pat = vpat[frame_par->vscale_skip_count]; |
| |
| if (type & VIDTYPE_VIU_FIELD) { |
| loop = 0; |
| |
| if (type & VIDTYPE_INTERLACE) |
| pat = vpat[frame_par->vscale_skip_count >> 1]; |
| } else if (is_mvc) { |
| loop = 0x11; |
| pat = 0x80; |
| } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { |
| loop = 0x11; |
| pat <<= 4; |
| } else { |
| loop = 0; |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_rpt_loop, |
| (loop << VDIF_CHROMA_LOOP1_BIT) | |
| (loop << VDIF_LUMA_LOOP1_BIT) | |
| (loop << VDIF_CHROMA_LOOP0_BIT) | |
| (loop << VDIF_LUMA_LOOP0_BIT)); |
| |
| if (is_mvc) |
| pat = 0x88; |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma0_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma0_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma1_rpt_pat, pat); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma1_rpt_pat, pat); |
| |
| /* picture 0/1 control */ |
| if ((((type & VIDTYPE_INTERLACE) == 0) && |
| ((type & VIDTYPE_VIU_FIELD) == 0) && |
| ((type & VIDTYPE_MVC) == 0)) || |
| (frame_par->vpp_2pic_mode & 0x3)) { |
| /* progressive frame in two pictures */ |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_psel, 0); |
| } |
| } |
| |
| static s32 vd1_afbc_setting_tl1(struct mif_pos_s *setting) |
| { |
| int crop_left, crop_top; |
| int vsize_in, hsize_in; |
| int mif_blk_bgn_h, mif_blk_end_h; |
| int mif_blk_bgn_v, mif_blk_end_v; |
| int pix_bgn_h, pix_end_h; |
| int pix_bgn_v, pix_end_v; |
| struct hw_afbc_reg_s *vd_afbc_reg; |
| |
| if (!setting) |
| return -1; |
| |
| vd_afbc_reg = setting->p_vd_afbc_reg; |
| /* afbc horizontal setting */ |
| crop_left = setting->start_x_lines; |
| hsize_in = round_up( |
| (setting->src_w - 1) + 1, 32); |
| mif_blk_bgn_h = crop_left / 32; |
| mif_blk_end_h = (crop_left + setting->end_x_lines - |
| setting->start_x_lines) / 32; |
| pix_bgn_h = crop_left - mif_blk_bgn_h * 32; |
| pix_end_h = pix_bgn_h + setting->end_x_lines - |
| setting->start_x_lines; |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_hor_scope, |
| (mif_blk_bgn_h << 16) | |
| mif_blk_end_h); |
| |
| if (((process_3d_type & MODE_3D_FA) || |
| (process_3d_type & MODE_FORCE_3D_FA_LR)) && |
| (setting->vpp_3d_mode == 1)) { |
| /* do nothing*/ |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_hor_scope, |
| ((pix_bgn_h << 16) | |
| pix_end_h)); |
| } |
| |
| /* afbc vertical setting */ |
| crop_top = setting->start_y_lines; |
| vsize_in = round_up((setting->src_h - 1) + 1, 4); |
| mif_blk_bgn_v = crop_top / 4; |
| mif_blk_end_v = (crop_top + setting->end_y_lines - |
| setting->start_y_lines) / 4; |
| pix_bgn_v = crop_top - mif_blk_bgn_v * 4; |
| pix_end_v = pix_bgn_v + setting->end_y_lines - |
| setting->start_y_lines; |
| |
| if (((process_3d_type & MODE_3D_FA) || |
| (process_3d_type & MODE_FORCE_3D_FA_TB)) && |
| (setting->vpp_3d_mode == 2)) { |
| int block_h; |
| |
| block_h = vsize_in; |
| block_h = block_h / 8; |
| if (toggle_3d_fa_frame == OUT_FA_B_FRAME) { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| (block_h << 16) | |
| (vsize_in / 4)); |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| (0 << 16) | |
| block_h); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| (mif_blk_bgn_v << 16) | |
| mif_blk_end_v); |
| } |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_ver_scope, |
| (pix_bgn_v << 16) | |
| pix_end_v); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_size_in, |
| (hsize_in << 16) | |
| (vsize_in & 0xffff)); |
| return 0; |
| } |
| |
| static s32 vd1_mif_setting(struct mif_pos_s *setting) |
| { |
| u32 ls = 0, le = 0; |
| u32 h_skip, v_skip, hc_skip, vc_skip; |
| int l_aligned, r_aligned; |
| int t_aligned, b_aligned, ori_t_aligned, ori_b_aligned; |
| int content_w, content_l, content_r; |
| struct hw_vd_reg_s *vd_mif_reg; |
| struct hw_afbc_reg_s *vd_afbc_reg; |
| |
| if (!setting) |
| return -1; |
| |
| vd_mif_reg = setting->p_vd_mif_reg; |
| vd_afbc_reg = setting->p_vd_afbc_reg; |
| h_skip = setting->h_skip + 1; |
| v_skip = setting->v_skip + 1; |
| hc_skip = setting->hc_skip; |
| vc_skip = setting->vc_skip; |
| |
| /* vd horizontal setting */ |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_x0, |
| (setting->l_hs_luma << VDIF_PIC_START_BIT) | |
| (setting->l_he_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_x0, |
| (setting->l_hs_chrm << VDIF_PIC_START_BIT) | |
| (setting->l_he_chrm << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_x1, |
| (setting->r_hs_luma << VDIF_PIC_START_BIT) | |
| (setting->r_he_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_x1, |
| (setting->r_hs_chrm << VDIF_PIC_START_BIT) | |
| (setting->r_he_chrm << VDIF_PIC_END_BIT)); |
| |
| ls = setting->start_x_lines; |
| le = setting->end_x_lines; |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->viu_vd_fmt_w, |
| (((le - ls + 1) / h_skip) |
| << VD1_FMT_LUMA_WIDTH_BIT) | |
| (((le / 2 - ls / 2 + 1) / h_skip) |
| << VD1_FMT_CHROMA_WIDTH_BIT)); |
| |
| /* vd vertical setting */ |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_y0, |
| (setting->l_vs_luma << VDIF_PIC_START_BIT) | |
| (setting->l_ve_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_y0, |
| (setting->l_vs_chrm << VDIF_PIC_START_BIT) | |
| (setting->l_ve_chrm << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_y1, |
| (setting->r_vs_luma << VDIF_PIC_START_BIT) | |
| (setting->r_ve_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_y1, |
| (setting->r_vs_chrm << VDIF_PIC_START_BIT) | |
| (setting->r_ve_chrm << VDIF_PIC_END_BIT)); |
| |
| if (setting->skip_afbc) |
| goto SKIP_VD1_AFBC; |
| |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) |
| return vd1_afbc_setting_tl1(setting); |
| |
| /* afbc horizontal setting */ |
| if ((setting->start_x_lines > 0) || |
| (setting->end_x_lines < (setting->src_w - 1))) { |
| /* also 0 line as start */ |
| l_aligned = round_down(0, 32); |
| r_aligned = round_up( |
| (setting->src_w - 1) + 1, 32); |
| } else { |
| l_aligned = round_down( |
| setting->start_x_lines, 32); |
| r_aligned = round_up( |
| setting->end_x_lines + 1, 32); |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_vd_cfmt_w, |
| (((r_aligned - l_aligned) / h_skip) << 16) | |
| ((r_aligned / 2 - l_aligned / hc_skip) / h_skip)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_hor_scope, |
| ((l_aligned / 32) << 16) | |
| ((r_aligned / 32) - 1)); |
| |
| if (setting->reverse) { |
| content_w = setting->end_x_lines |
| - setting->start_x_lines + 1; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) |
| content_l = 0; |
| else |
| content_l = r_aligned - setting->end_x_lines - 1; |
| content_r = content_l + content_w - 1; |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_hor_scope, |
| (((content_l << 16)) | content_r) / h_skip); |
| } else { |
| if (((process_3d_type & MODE_3D_FA) || |
| (process_3d_type & MODE_FORCE_3D_FA_LR)) && |
| (setting->vpp_3d_mode == 1)) { |
| /* do nothing*/ |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_hor_scope, |
| (((setting->start_x_lines - l_aligned) << 16) | |
| (setting->end_x_lines - l_aligned)) / h_skip); |
| } |
| } |
| |
| /* afbc vertical setting */ |
| t_aligned = round_down(setting->start_y_lines, 4); |
| b_aligned = round_up(setting->end_y_lines + 1, 4); |
| |
| ori_t_aligned = round_down(0, 4); |
| ori_b_aligned = round_up((setting->src_h - 1) + 1, 4); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_vd_cfmt_h, |
| (b_aligned - t_aligned) / vc_skip / v_skip); |
| |
| if (((process_3d_type & MODE_3D_FA) || |
| (process_3d_type & MODE_FORCE_3D_FA_TB)) && |
| (setting->vpp_3d_mode == 2)) { |
| int block_h; |
| |
| block_h = ori_b_aligned - ori_t_aligned; |
| block_h = block_h / 8; |
| if (toggle_3d_fa_frame == OUT_FA_B_FRAME) { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| (((ori_t_aligned / 4) + block_h) << 16) | |
| ((ori_b_aligned / 4) - 1)); |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| ((ori_t_aligned / 4) << 16) | |
| ((ori_t_aligned / 4) + block_h - 1)); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| ((t_aligned / 4) << 16) | |
| ((b_aligned / 4) - 1)); |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| ((t_aligned / 4) << 16) | |
| ((b_aligned / 4) - 1)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_ver_scope, |
| ((setting->start_y_lines - t_aligned) << 16) | |
| (setting->end_y_lines - t_aligned)); |
| |
| /* TODO: if need remove this limit */ |
| /* afbc pixel vertical output region must be */ |
| /* [0, end_y_lines - start_y_lines] */ |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_ver_scope, |
| (setting->end_y_lines - |
| setting->start_y_lines)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_size_in, |
| ((r_aligned - l_aligned) << 16) | |
| ((ori_b_aligned - ori_t_aligned) & 0xffff)); |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_size_out, |
| (((r_aligned - l_aligned) / h_skip) << 16) | |
| (((b_aligned - t_aligned) / v_skip) & 0xffff)); |
| } |
| SKIP_VD1_AFBC: |
| return 0; |
| } |
| |
| static s32 vd2_afbc_setting_tl1(struct mif_pos_s *setting) |
| { |
| int crop_left, crop_top; |
| int vsize_in, hsize_in; |
| int mif_blk_bgn_h, mif_blk_end_h; |
| int mif_blk_bgn_v, mif_blk_end_v; |
| int pix_bgn_h, pix_end_h; |
| int pix_bgn_v, pix_end_v; |
| struct hw_afbc_reg_s *vd2_afbc_reg; |
| |
| if (!setting) |
| return -1; |
| |
| vd2_afbc_reg = setting->p_vd_afbc_reg; |
| /* afbc horizontal setting */ |
| crop_left = setting->start_x_lines; |
| hsize_in = round_up( |
| (setting->src_w - 1) + 1, 32); |
| mif_blk_bgn_h = crop_left / 32; |
| mif_blk_end_h = (crop_left + setting->end_x_lines - |
| setting->start_x_lines) / 32; |
| pix_bgn_h = crop_left - mif_blk_bgn_h * 32; |
| pix_end_h = pix_bgn_h + setting->end_x_lines - |
| setting->start_x_lines; |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_mif_hor_scope, |
| (mif_blk_bgn_h << 16) | |
| mif_blk_end_h); |
| |
| if (((process_3d_type & MODE_3D_FA) || |
| (process_3d_type & MODE_FORCE_3D_FA_LR)) && |
| (setting->vpp_3d_mode == 1)) { |
| /* do nothing*/ |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_pixel_hor_scope, |
| ((pix_bgn_h << 16) | |
| pix_end_h)); |
| } |
| |
| /* afbc vertical setting */ |
| crop_top = setting->start_y_lines; |
| vsize_in = round_up((setting->src_h - 1) + 1, 4); |
| mif_blk_bgn_v = crop_top / 4; |
| mif_blk_end_v = (crop_top + setting->end_y_lines - |
| setting->start_y_lines) / 4; |
| pix_bgn_v = crop_top - mif_blk_bgn_v * 4; |
| pix_end_v = pix_bgn_v + setting->end_y_lines - |
| setting->start_y_lines; |
| |
| if (((process_3d_type & MODE_3D_FA) || |
| (process_3d_type & MODE_FORCE_3D_FA_TB)) && |
| (setting->vpp_3d_mode == 2)) { |
| int block_h; |
| |
| block_h = vsize_in; |
| block_h = block_h / 8; |
| if (toggle_3d_fa_frame == OUT_FA_B_FRAME) { |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_mif_ver_scope, |
| (block_h << 16) | |
| (vsize_in / 4)); |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_mif_ver_scope, |
| (0 << 16) | |
| block_h); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_mif_ver_scope, |
| (mif_blk_bgn_v << 16) | |
| mif_blk_end_v); |
| } |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_pixel_ver_scope, |
| (pix_bgn_v << 16) | |
| pix_end_v); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_size_in, |
| (hsize_in << 16) | |
| (vsize_in & 0xffff)); |
| return 0; |
| } |
| |
| static s32 vd2_mif_setting(struct mif_pos_s *setting) |
| { |
| u32 ls = 0, le = 0; |
| u32 h_skip, v_skip, hc_skip, vc_skip; |
| int l_aligned, r_aligned; |
| int t_aligned, b_aligned, ori_t_aligned, ori_b_aligned; |
| int content_w, content_l, content_r; |
| struct hw_vd_reg_s *vd2_mif_reg; |
| struct hw_afbc_reg_s *vd2_afbc_reg; |
| |
| if (!setting) |
| return -1; |
| |
| vd2_mif_reg = setting->p_vd_mif_reg; |
| vd2_afbc_reg = setting->p_vd_afbc_reg; |
| h_skip = setting->h_skip + 1; |
| v_skip = setting->v_skip + 1; |
| hc_skip = setting->hc_skip; |
| vc_skip = setting->vc_skip; |
| |
| /* vd horizontal setting */ |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_x0, |
| (setting->l_hs_luma << VDIF_PIC_START_BIT) | |
| (setting->l_he_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_x0, |
| (setting->l_hs_chrm << VDIF_PIC_START_BIT) | |
| (setting->l_he_chrm << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_x1, |
| (setting->r_hs_luma << VDIF_PIC_START_BIT) | |
| (setting->r_he_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_x1, |
| (setting->r_hs_chrm << VDIF_PIC_START_BIT) | |
| (setting->r_he_chrm << VDIF_PIC_END_BIT)); |
| |
| ls = setting->start_x_lines; |
| le = setting->end_x_lines; |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->viu_vd_fmt_w, |
| (((le - ls + 1) / h_skip) |
| << VD1_FMT_LUMA_WIDTH_BIT) | |
| (((le / 2 - ls / 2 + 1) / h_skip) |
| << VD1_FMT_CHROMA_WIDTH_BIT)); |
| |
| /* vd vertical setting */ |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_y0, |
| (setting->l_vs_luma << VDIF_PIC_START_BIT) | |
| (setting->l_ve_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_y0, |
| (setting->l_vs_chrm << VDIF_PIC_START_BIT) | |
| (setting->l_ve_chrm << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_y1, |
| (setting->r_vs_luma << VDIF_PIC_START_BIT) | |
| (setting->r_ve_luma << VDIF_PIC_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_y1, |
| (setting->r_vs_chrm << VDIF_PIC_START_BIT) | |
| (setting->r_ve_chrm << VDIF_PIC_END_BIT)); |
| |
| if (setting->skip_afbc) |
| goto SKIP_VD2_AFBC; |
| |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) |
| return vd2_afbc_setting_tl1(setting); |
| |
| /* afbc horizontal setting */ |
| if ((setting->start_x_lines > 0) || |
| (setting->end_x_lines < (setting->src_w - 1))) { |
| /* also 0 line as start */ |
| l_aligned = round_down(0, 32); |
| r_aligned = round_up( |
| (setting->src_w - 1) + 1, 32); |
| } else { |
| l_aligned = round_down( |
| setting->start_x_lines, 32); |
| r_aligned = round_up( |
| setting->end_x_lines + 1, 32); |
| } |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_vd_cfmt_w, |
| (((r_aligned - l_aligned) / h_skip) << 16) | |
| ((r_aligned / 2 - l_aligned / hc_skip) / h_skip)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_mif_hor_scope, |
| ((l_aligned / 32) << 16) | |
| ((r_aligned / 32) - 1)); |
| |
| if (setting->reverse) { |
| content_w = setting->end_x_lines |
| - setting->start_x_lines + 1; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) |
| content_l = 0; |
| else |
| content_l = (r_aligned - setting->end_x_lines - 1) |
| + (setting->start_x_lines - l_aligned); |
| /* TODO: content_l = r_aligned - setting->end_x_lines - 1; */ |
| content_r = content_l + content_w - 1; |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_pixel_hor_scope, |
| (((content_l << 16)) | content_r) / h_skip); |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_pixel_hor_scope, |
| (((setting->start_x_lines - l_aligned) << 16) | |
| (setting->end_x_lines - l_aligned)) / h_skip); |
| } |
| |
| /* afbc vertical setting */ |
| t_aligned = round_down(setting->start_y_lines, 4); |
| b_aligned = round_up(setting->end_y_lines + 1, 4); |
| |
| ori_t_aligned = round_down(0, 4); |
| ori_b_aligned = round_up((setting->src_h - 1) + 1, 4); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_vd_cfmt_h, |
| (b_aligned - t_aligned) / vc_skip / v_skip); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_mif_ver_scope, |
| ((t_aligned / 4) << 16) | |
| ((b_aligned / 4) - 1)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_pixel_ver_scope, |
| ((setting->start_y_lines - t_aligned) << 16) | |
| (setting->end_y_lines - t_aligned)); |
| |
| /* TODO: if need remove this limit */ |
| /* afbc pixel vertical output region must be */ |
| /* [0, end_y_lines - start_y_lines] */ |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_pixel_ver_scope, |
| (setting->end_y_lines - setting->start_y_lines)); |
| |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_size_in, |
| ((r_aligned - l_aligned) << 16) | |
| ((ori_b_aligned - ori_t_aligned) & 0xffff)); |
| if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { |
| VSYNC_WR_MPEG_REG( |
| vd2_afbc_reg->afbc_size_out, |
| (((r_aligned - l_aligned) / h_skip) << 16) | |
| (((b_aligned - t_aligned) / v_skip) & 0xffff)); |
| } |
| SKIP_VD2_AFBC: |
| return 0; |
| } |
| |
| static void vd1_scaler_setting( |
| struct scaler_setting_s *setting) |
| { |
| u32 misc_off, i; |
| u32 r1, r2, r3; |
| struct vpp_frame_par_s *frame_par; |
| struct vppfilter_mode_s *vpp_filter; |
| u32 hsc_rpt_p0_num0 = 1; |
| u32 hsc_init_rev_num0 = 4; |
| u32 bit9_mode = 0; |
| |
| if (!setting || !setting->frame_par) |
| return; |
| |
| frame_par = setting->frame_par; |
| misc_off = setting->misc_reg_offt; |
| |
| /* vpp super scaler */ |
| vpp_set_super_scaler_regs( |
| frame_par->supscl_path, |
| frame_par->supsc0_enable, |
| frame_par->spsc0_w_in, |
| frame_par->spsc0_h_in, |
| frame_par->supsc0_hori_ratio, |
| frame_par->supsc0_vert_ratio, |
| frame_par->supsc1_enable, |
| frame_par->spsc1_w_in, |
| frame_par->spsc1_h_in, |
| frame_par->supsc1_hori_ratio, |
| frame_par->supsc1_vert_ratio, |
| setting->force_disable_sr, |
| setting->vinfo_width, |
| setting->vinfo_height); |
| |
| if (is_dolby_vision_on() && |
| is_dolby_vision_stb_mode() && |
| !frame_par->supsc0_enable && |
| !frame_par->supsc1_enable) { |
| VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0); |
| VSYNC_WR_MPEG_REG(VPP_SRSHARP1_CTRL, 0); |
| } |
| |
| vpp_filter = &frame_par->vpp_filter; |
| |
| if (setting->sc_top_enable) { |
| u32 sc_misc_val; |
| |
| sc_misc_val = VPP_SC_TOP_EN | VPP_SC_V1OUT_EN; |
| if (setting->sc_h_enable) { |
| if (has_pre_hscaler_ntap(0)) { |
| /* for sc2/t5 support hscaler 8 tap */ |
| if (pre_hscaler_ntap_enable[0]) { |
| sc_misc_val |= |
| (((vpp_filter->vpp_pre_hsc_en & 1) |
| << VPP_SC_PREHORZ_EN_BIT) |
| | VPP_SC_HORZ_EN); |
| } else { |
| sc_misc_val |= |
| (((vpp_filter->vpp_pre_hsc_en & 1) |
| << VPP_SC_PREHORZ_EN_BIT_OLD) |
| | VPP_SC_HORZ_EN); |
| } |
| } else { |
| sc_misc_val |= |
| (((vpp_filter->vpp_pre_hsc_en & 1) |
| << VPP_SC_PREHORZ_EN_BIT) |
| | VPP_SC_HORZ_EN); |
| } |
| if (hscaler_8tap_enable[0]) { |
| sc_misc_val |= |
| ((vpp_filter->vpp_horz_coeff[0] & 0xf) |
| << VPP_SC_HBANK_LENGTH_BIT); |
| |
| } else { |
| sc_misc_val |= |
| ((vpp_filter->vpp_horz_coeff[0] & 7) |
| << VPP_SC_HBANK_LENGTH_BIT); |
| } |
| } |
| |
| if (setting->sc_v_enable) { |
| sc_misc_val |= (((vpp_filter->vpp_pre_vsc_en & 1) |
| << VPP_SC_PREVERT_EN_BIT) |
| | VPP_SC_VERT_EN); |
| sc_misc_val |= ((vpp_filter->vpp_pre_vsc_en & 1) |
| << VPP_LINE_BUFFER_EN_BIT); |
| sc_misc_val |= ((vpp_filter->vpp_vert_coeff[0] & 7) |
| << VPP_SC_VBANK_LENGTH_BIT); |
| } |
| |
| if (setting->last_line_fix) |
| sc_misc_val |= VPP_PPS_LAST_LINE_FIX; |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_SC_MISC + misc_off, |
| sc_misc_val); |
| } else { |
| setting->sc_v_enable = false; |
| setting->sc_h_enable = false; |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_SC_MISC + misc_off, |
| 0, VPP_SC_TOP_EN_BIT, |
| VPP_SC_TOP_EN_WID); |
| } |
| |
| /* horitontal filter settings */ |
| if (setting->sc_h_enable) { |
| bit9_mode = vpp_filter->vpp_horz_coeff[1] & 0x8000; |
| if (hscaler_8tap_enable[0]) { |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | VPP_COEF_9BIT); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | |
| VPP_COEF_VERT_CHROMA | |
| VPP_COEF_9BIT); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM * 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM * 3]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | |
| VPP_COEF_VERT_CHROMA); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } |
| } else { |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | VPP_COEF_9BIT); |
| for (i = 0; i < |
| (vpp_filter->vpp_horz_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ); |
| for (i = 0; i < (vpp_filter->vpp_horz_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG |
| (VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| } |
| } |
| r1 = frame_par->VPP_hsc_linear_startp |
| - frame_par->VPP_hsc_startp; |
| r2 = frame_par->VPP_hsc_linear_endp |
| - frame_par->VPP_hsc_startp; |
| r3 = frame_par->VPP_hsc_endp |
| - frame_par->VPP_hsc_startp; |
| |
| if ((frame_par->supscl_path == |
| CORE0_PPS_CORE1) || |
| (frame_par->supscl_path == |
| CORE1_AFTER_PPS) || |
| (frame_par->supscl_path == |
| PPS_CORE0_CORE1) || |
| (frame_par->supscl_path == |
| PPS_CORE0_POSTBLEND_CORE1)) |
| r3 >>= frame_par->supsc1_hori_ratio; |
| if ((frame_par->supscl_path == |
| CORE0_AFTER_PPS) || |
| (frame_par->supscl_path == |
| PPS_CORE0_CORE1) || |
| (frame_par->supscl_path == |
| PPS_CORE0_POSTBLEND_CORE1)) |
| r3 >>= frame_par->supsc0_hori_ratio; |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_HSC_PHASE_CTRL + misc_off, |
| frame_par->VPP_hf_ini_phase_, |
| VPP_HSC_TOP_INI_PHASE_BIT, |
| VPP_HSC_TOP_INI_PHASE_WID); |
| if (has_pre_hscaler_ntap(0)) { |
| int ds_ratio = 1; |
| int flt_num = 4; |
| int pre_hscaler_table[4] = { |
| 0x0, 0x0, 0xf8, 0x48}; |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_HSC_PHASE_CTRL1 + misc_off, |
| frame_par->VPP_hf_ini_phase_, |
| VPP_HSC_TOP_INI_PHASE_BIT, |
| VPP_HSC_TOP_INI_PHASE_WID); |
| if (hscaler_8tap_enable[0]) { |
| hsc_rpt_p0_num0 = 3; |
| hsc_init_rev_num0 = 8; |
| } else { |
| hsc_init_rev_num0 = 4; |
| hsc_rpt_p0_num0 = 1; |
| } |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_HSC_PHASE_CTRL + misc_off, |
| hsc_init_rev_num0, |
| VPP_HSC_INIRCV_NUM_BIT, |
| VPP_HSC_INIRCV_NUM_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_HSC_PHASE_CTRL + misc_off, |
| hsc_rpt_p0_num0, |
| VPP_HSC_INIRPT_NUM_BIT_8TAP, |
| VPP_HSC_INIRPT_NUM_WID_8TAP); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_HSC_PHASE_CTRL1 + misc_off, |
| hsc_init_rev_num0, |
| VPP_HSC_INIRCV_NUM_BIT, |
| VPP_HSC_INIRCV_NUM_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_HSC_PHASE_CTRL1 + misc_off, |
| hsc_rpt_p0_num0, |
| VPP_HSC_INIRPT_NUM_BIT_8TAP, |
| VPP_HSC_INIRPT_NUM_WID_8TAP); |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREHSC_COEF + misc_off, |
| pre_hscaler_table[0], |
| VPP_PREHSC_COEF0_BIT, |
| VPP_PREHSC_COEF0_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREHSC_COEF + misc_off, |
| pre_hscaler_table[1], |
| VPP_PREHSC_COEF1_BIT, |
| VPP_PREHSC_COEF1_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREHSC_COEF + misc_off, |
| pre_hscaler_table[2], |
| VPP_PREHSC_COEF2_BIT, |
| VPP_PREHSC_COEF2_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREHSC_COEF + misc_off, |
| pre_hscaler_table[3], |
| VPP_PREHSC_COEF3_BIT, |
| VPP_PREHSC_COEF3_WID); |
| if (has_pre_vscaler_ntap(0)) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PRE_SCALE_CTRL + misc_off, |
| flt_num, |
| VPP_PREHSC_FLT_NUM_BIT_T5, |
| VPP_PREHSC_FLT_NUM_WID_T5); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PRE_SCALE_CTRL + misc_off, |
| ds_ratio, |
| VPP_PREVSC_DS_RATIO_BIT_T5, |
| VPP_PREVSC_DS_RATIO_WID_T5); |
| } else { |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREHSC_CTRL + misc_off, |
| flt_num, |
| VPP_PREHSC_FLT_NUM_BIT, |
| VPP_PREHSC_FLT_NUM_WID); |
| } |
| } |
| if (has_pre_vscaler_ntap(0)) { |
| int ds_ratio = 1; |
| int flt_num = 4; |
| int pre_vscaler_table[2] = { |
| 0xf8, 0x48}; |
| |
| if (!pre_vscaler_ntap_enable[0]) { |
| pre_vscaler_table[0] = 0; |
| pre_vscaler_table[1] = 0x40; |
| flt_num = 2; |
| } |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREVSC_COEF + misc_off, |
| pre_vscaler_table[0], |
| VPP_PREVSC_COEF0_BIT, |
| VPP_PREVSC_COEF0_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PREVSC_COEF + misc_off, |
| pre_vscaler_table[1], |
| VPP_PREVSC_COEF1_BIT, |
| VPP_PREVSC_COEF1_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PRE_SCALE_CTRL + misc_off, |
| flt_num, |
| VPP_PREVSC_FLT_NUM_BIT_T5, |
| VPP_PREVSC_FLT_NUM_WID_T5); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_PRE_SCALE_CTRL + misc_off, |
| ds_ratio, |
| VPP_PREVSC_DS_RATIO_BIT_T5, |
| VPP_PREVSC_DS_RATIO_WID_T5); |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_HSC_REGION12_STARTP + misc_off, |
| (0 << VPP_REGION1_BIT) | |
| ((r1 & VPP_REGION_MASK) |
| << VPP_REGION2_BIT)); |
| VSYNC_WR_MPEG_REG( |
| VPP_HSC_REGION34_STARTP + misc_off, |
| ((r2 & VPP_REGION_MASK) |
| << VPP_REGION3_BIT) | |
| ((r3 & VPP_REGION_MASK) |
| << VPP_REGION4_BIT)); |
| VSYNC_WR_MPEG_REG( |
| VPP_HSC_REGION4_ENDP + misc_off, r3); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_HSC_START_PHASE_STEP + misc_off, |
| vpp_filter->vpp_hf_start_phase_step); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_HSC_REGION1_PHASE_SLOPE + misc_off, |
| vpp_filter->vpp_hf_start_phase_slope); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_HSC_REGION3_PHASE_SLOPE + misc_off, |
| vpp_filter->vpp_hf_end_phase_slope); |
| } |
| |
| /* vertical filter settings */ |
| if (setting->sc_v_enable) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_VSC_PHASE_CTRL + misc_off, |
| (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, |
| VPP_PHASECTL_DOUBLELINE_BIT, |
| VPP_PHASECTL_DOUBLELINE_WID); |
| |
| bit9_mode = vpp_filter->vpp_vert_coeff[1] & 0x8000; |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT | |
| VPP_COEF_9BIT); |
| for (i = 0; i < (vpp_filter->vpp_vert_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_vert_coeff[i + 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_vert_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT); |
| for (i = 0; i < (vpp_filter->vpp_vert_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF + misc_off, |
| vpp_filter->vpp_vert_coeff[i + 2]); |
| } |
| } |
| /* vertical chroma filter settings */ |
| if (vpp_filter->vpp_vert_chroma_filter_en) { |
| const u32 *pcoeff = vpp_filter->vpp_vert_chroma_coeff; |
| |
| bit9_mode = pcoeff[1] & 0x8000; |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT_CHROMA | VPP_COEF_SEP_EN); |
| for (i = 0; i < pcoeff[1]; i++) |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF + misc_off, |
| pcoeff[i + 2]); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF + misc_off, |
| pcoeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT_CHROMA | VPP_COEF_SEP_EN); |
| for (i = 0; i < pcoeff[1]; i++) |
| VSYNC_WR_MPEG_REG( |
| VPP_SCALE_COEF + misc_off, |
| pcoeff[i + 2]); |
| } |
| } |
| |
| r1 = frame_par->VPP_vsc_endp |
| - frame_par->VPP_vsc_startp; |
| VSYNC_WR_MPEG_REG( |
| VPP_VSC_REGION12_STARTP + misc_off, 0); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_VSC_REGION34_STARTP + misc_off, |
| ((r1 & VPP_REGION_MASK) |
| << VPP_REGION3_BIT) | |
| ((r1 & VPP_REGION_MASK) |
| << VPP_REGION4_BIT)); |
| |
| if ((frame_par->supscl_path == |
| CORE0_PPS_CORE1) || |
| (frame_par->supscl_path == |
| CORE1_AFTER_PPS) || |
| (frame_par->supscl_path == |
| PPS_CORE0_POSTBLEND_CORE1)) |
| r1 >>= frame_par->supsc1_vert_ratio; |
| if ((frame_par->supscl_path == |
| CORE0_AFTER_PPS) || |
| (frame_par->supscl_path == |
| PPS_CORE0_CORE1) || |
| (frame_par->supscl_path == |
| PPS_CORE0_POSTBLEND_CORE1)) |
| r1 >>= frame_par->supsc0_vert_ratio; |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_VSC_REGION4_ENDP + misc_off, r1); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_VSC_START_PHASE_STEP + misc_off, |
| vpp_filter->vpp_vsc_start_phase_step); |
| } |
| |
| /*vpp input size setting*/ |
| VSYNC_WR_MPEG_REG( |
| VPP_IN_H_V_SIZE + misc_off, |
| ((frame_par->video_input_w & 0x1fff) << 16) |
| | (frame_par->video_input_h & 0x1fff)); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_PIC_IN_HEIGHT + misc_off, |
| frame_par->VPP_pic_in_height_); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_LINE_IN_LENGTH + misc_off, |
| frame_par->VPP_line_in_length_); |
| |
| /* FIXME: if enable it */ |
| #ifdef CHECK_LATER |
| if (vd_layer[0].enabled == 1) { |
| struct vppfilter_mode_s *vpp_filter = |
| &cur_frame_par->vpp_filter; |
| u32 h_phase_step, v_phase_step; |
| |
| h_phase_step = READ_VCBUS_REG( |
| VPP_HSC_START_PHASE_STEP + misc_off); |
| v_phase_step = READ_VCBUS_REG( |
| VPP_VSC_START_PHASE_STEP + misc_off); |
| if ((vpp_filter->vpp_hf_start_phase_step != h_phase_step) || |
| (vpp_filter->vpp_vsc_start_phase_step != v_phase_step)) |
| vd_layer[0].property_changed = true; |
| } |
| #endif |
| } |
| |
| static void vd2_scaler_setting( |
| struct scaler_setting_s *setting) |
| { |
| u32 misc_off, i; |
| u32 r1, r2, r3; |
| struct vpp_frame_par_s *frame_par; |
| struct vppfilter_mode_s *vpp_filter; |
| u32 hsc_rpt_p0_num0 = 1; |
| u32 hsc_init_rev_num0 = 4; |
| u32 bit9_mode = 0; |
| |
| if (!setting || !setting->frame_par) |
| return; |
| |
| frame_par = setting->frame_par; |
| misc_off = setting->misc_reg_offt; |
| vpp_filter = &frame_par->vpp_filter; |
| |
| if (setting->sc_top_enable) { |
| u32 sc_misc_val; |
| |
| sc_misc_val = VPP_SC_TOP_EN | VPP_SC_V1OUT_EN; |
| if (setting->sc_h_enable) { |
| if (has_pre_hscaler_ntap(1)) { |
| if (pre_hscaler_ntap_enable[1]) { |
| sc_misc_val |= |
| (((vpp_filter->vpp_pre_hsc_en & 1) |
| << VPP_SC_PREHORZ_EN_BIT) |
| | VPP_SC_HORZ_EN); |
| } else { |
| sc_misc_val |= |
| (((vpp_filter->vpp_pre_hsc_en & 1) |
| << VPP_SC_PREHORZ_EN_BIT_OLD) |
| | VPP_SC_HORZ_EN); |
| } |
| } else |
| sc_misc_val |= |
| (((vpp_filter->vpp_pre_hsc_en & 1) |
| << VPP_SC_PREHORZ_EN_BIT) |
| | VPP_SC_HORZ_EN); |
| if (hscaler_8tap_enable[1]) |
| sc_misc_val |= |
| ((vpp_filter->vpp_horz_coeff[0] & 0xf) |
| << VPP_SC_HBANK_LENGTH_BIT); |
| else |
| sc_misc_val |= |
| ((vpp_filter->vpp_horz_coeff[0] & 7) |
| << VPP_SC_HBANK_LENGTH_BIT); |
| } |
| |
| if (setting->sc_v_enable) { |
| sc_misc_val |= (((vpp_filter->vpp_pre_vsc_en & 1) |
| << VPP_SC_PREVERT_EN_BIT) |
| | VPP_SC_VERT_EN); |
| sc_misc_val |= ((vpp_filter->vpp_pre_vsc_en & 1) |
| << VPP_LINE_BUFFER_EN_BIT); |
| sc_misc_val |= ((vpp_filter->vpp_vert_coeff[0] & 7) |
| << VPP_SC_VBANK_LENGTH_BIT); |
| } |
| |
| if (setting->last_line_fix) |
| sc_misc_val |= VPP_PPS_LAST_LINE_FIX; |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_SC_MISC + misc_off, |
| sc_misc_val); |
| } else { |
| setting->sc_v_enable = false; |
| setting->sc_h_enable = false; |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_SC_MISC + misc_off, |
| 0, VPP_SC_TOP_EN_BIT, |
| VPP_SC_TOP_EN_WID); |
| } |
| |
| /* horitontal filter settings */ |
| if (setting->sc_h_enable) { |
| bit9_mode = vpp_filter->vpp_horz_coeff[1] & 0x8000; |
| if (hscaler_8tap_enable[1]) { |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | VPP_COEF_9BIT); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| VSYNC_WR_MPEG_REG(VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | |
| VPP_COEF_VERT_CHROMA | |
| VPP_COEF_9BIT); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM * 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM * 3]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG(VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| VSYNC_WR_MPEG_REG(VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | |
| VPP_COEF_VERT_CHROMA); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } |
| } else { |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ | VPP_COEF_9BIT); |
| for (i = 0; i < (vpp_filter->vpp_horz_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_HORZ); |
| for (i = 0; i < (vpp_filter->vpp_horz_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG |
| (VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_horz_coeff[i + 2]); |
| } |
| } |
| } |
| r1 = frame_par->VPP_hsc_linear_startp |
| - frame_par->VPP_hsc_startp; |
| r2 = frame_par->VPP_hsc_linear_endp |
| - frame_par->VPP_hsc_startp; |
| r3 = frame_par->VPP_hsc_endp |
| - frame_par->VPP_hsc_startp; |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_HSC_PHASE_CTRL + misc_off, |
| frame_par->VPP_hf_ini_phase_, |
| VPP_HSC_TOP_INI_PHASE_BIT, |
| VPP_HSC_TOP_INI_PHASE_WID); |
| |
| if (has_pre_hscaler_ntap(1)) { |
| int flt_num = 4; |
| int pre_hscaler_table[4] = { |
| 0x0, 0x0, 0xf8, 0x48}; |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_HSC_PHASE_CTRL1 + misc_off, |
| frame_par->VPP_hf_ini_phase_, |
| VPP_HSC_TOP_INI_PHASE_BIT, |
| VPP_HSC_TOP_INI_PHASE_WID); |
| if (hscaler_8tap_enable[1]) { |
| hsc_rpt_p0_num0 = 3; |
| hsc_init_rev_num0 = 8; |
| } else { |
| hsc_init_rev_num0 = 4; |
| hsc_rpt_p0_num0 = 1; |
| } |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_HSC_PHASE_CTRL + misc_off, |
| hsc_init_rev_num0, |
| VPP_HSC_INIRCV_NUM_BIT, |
| VPP_HSC_INIRCV_NUM_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_HSC_PHASE_CTRL + misc_off, |
| hsc_rpt_p0_num0, |
| VPP_HSC_INIRPT_NUM_BIT_8TAP, |
| VPP_HSC_INIRPT_NUM_WID_8TAP); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_HSC_PHASE_CTRL1 + misc_off, |
| hsc_init_rev_num0, |
| VPP_HSC_INIRCV_NUM_BIT, |
| VPP_HSC_INIRCV_NUM_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_HSC_PHASE_CTRL1 + misc_off, |
| hsc_rpt_p0_num0, |
| VPP_HSC_INIRPT_NUM_BIT_8TAP, |
| VPP_HSC_INIRPT_NUM_WID_8TAP); |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_PREHSC_COEF + misc_off, |
| pre_hscaler_table[0], |
| VPP_PREHSC_COEF0_BIT, |
| VPP_PREHSC_COEF0_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_PREHSC_COEF + misc_off, |
| pre_hscaler_table[1], |
| VPP_PREHSC_COEF1_BIT, |
| VPP_PREHSC_COEF1_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_PREHSC_COEF + misc_off, |
| pre_hscaler_table[2], |
| VPP_PREHSC_COEF2_BIT, |
| VPP_PREHSC_COEF2_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_PREHSC_COEF + misc_off, |
| pre_hscaler_table[3], |
| VPP_PREHSC_COEF3_BIT, |
| VPP_PREHSC_COEF3_WID); |
| if (has_pre_hscaler_ntap(1)) |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_PREHSC_CTRL + misc_off, |
| flt_num, |
| VPP_PREHSC_FLT_NUM_BIT, |
| VPP_PREHSC_FLT_NUM_WID); |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_HSC_REGION12_STARTP + misc_off, |
| (0 << VPP_REGION1_BIT) | |
| ((r1 & VPP_REGION_MASK) |
| << VPP_REGION2_BIT)); |
| VSYNC_WR_MPEG_REG( |
| VD2_HSC_REGION34_STARTP + misc_off, |
| ((r2 & VPP_REGION_MASK) |
| << VPP_REGION3_BIT) | |
| ((r3 & VPP_REGION_MASK) |
| << VPP_REGION4_BIT)); |
| VSYNC_WR_MPEG_REG( |
| VD2_HSC_REGION4_ENDP + misc_off, r3); |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_HSC_START_PHASE_STEP + misc_off, |
| vpp_filter->vpp_hf_start_phase_step); |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_HSC_REGION1_PHASE_SLOPE + misc_off, |
| vpp_filter->vpp_hf_start_phase_slope); |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_HSC_REGION3_PHASE_SLOPE + misc_off, |
| vpp_filter->vpp_hf_end_phase_slope); |
| } |
| |
| /* vertical filter settings */ |
| if (setting->sc_v_enable) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_VSC_PHASE_CTRL + misc_off, |
| (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, |
| VPP_PHASECTL_DOUBLELINE_BIT, |
| VPP_PHASECTL_DOUBLELINE_WID); |
| bit9_mode = vpp_filter->vpp_vert_coeff[1] & 0x8000; |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT | |
| VPP_COEF_9BIT); |
| for (i = 0; i < (vpp_filter->vpp_vert_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_vert_coeff[i + 2]); |
| } |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_vert_coeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT); |
| for (i = 0; i < (vpp_filter->vpp_vert_coeff[1] |
| & 0xff); i++) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF + misc_off, |
| vpp_filter->vpp_vert_coeff[i + 2]); |
| } |
| } |
| |
| /* vertical chroma filter settings */ |
| if (vpp_filter->vpp_vert_chroma_filter_en) { |
| const u32 *pcoeff = vpp_filter->vpp_vert_chroma_coeff; |
| |
| bit9_mode = pcoeff[1] & 0x8000; |
| if (bit9_mode) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT_CHROMA | VPP_COEF_SEP_EN); |
| for (i = 0; i < pcoeff[1]; i++) |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF + misc_off, |
| pcoeff[i + 2]); |
| for (i = 0; i < VPP_FILER_COEFS_NUM; i++) { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF + misc_off, |
| pcoeff[i + 2 + |
| VPP_FILER_COEFS_NUM]); |
| } |
| } else { |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF_IDX + misc_off, |
| VPP_COEF_VERT_CHROMA | VPP_COEF_SEP_EN); |
| for (i = 0; i < pcoeff[1]; i++) |
| VSYNC_WR_MPEG_REG( |
| VD2_SCALE_COEF + misc_off, |
| pcoeff[i + 2]); |
| } |
| } |
| |
| r1 = frame_par->VPP_vsc_endp |
| - frame_par->VPP_vsc_startp; |
| VSYNC_WR_MPEG_REG( |
| VD2_VSC_REGION12_STARTP + misc_off, 0); |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_VSC_REGION34_STARTP + misc_off, |
| ((r1 & VPP_REGION_MASK) |
| << VPP_REGION3_BIT) | |
| ((r1 & VPP_REGION_MASK) |
| << VPP_REGION4_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_VSC_REGION4_ENDP + misc_off, r1); |
| |
| VSYNC_WR_MPEG_REG( |
| VD2_VSC_START_PHASE_STEP + misc_off, |
| vpp_filter->vpp_vsc_start_phase_step); |
| } |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_VD2_HDR_IN_SIZE + misc_off, |
| (frame_par->VPP_pic_in_height_ << 16) |
| | frame_par->VPP_line_in_length_); |
| } |
| |
| static void vd1_blend_setting( |
| struct blend_setting_s *setting) |
| { |
| u32 misc_off; |
| u32 vd_size_mask = VPP_VD_SIZE_MASK; |
| |
| if (!setting) |
| return; |
| |
| /* g12a change to 13 bits */ |
| if (!legacy_vpp) |
| vd_size_mask = 0x1fff; |
| |
| misc_off = setting->misc_reg_offt; |
| |
| /* preblend setting */ |
| VSYNC_WR_MPEG_REG( |
| VPP_PREBLEND_VD1_H_START_END + misc_off, |
| ((setting->preblend_h_start & vd_size_mask) |
| << VPP_VD1_START_BIT) | |
| ((setting->preblend_h_end & vd_size_mask) |
| << VPP_VD1_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_PREBLEND_VD1_V_START_END + misc_off, |
| ((setting->preblend_v_start & vd_size_mask) |
| << VPP_VD1_START_BIT) | |
| ((setting->preblend_v_end & vd_size_mask) |
| << VPP_VD1_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_PREBLEND_H_SIZE + misc_off, |
| setting->preblend_h_size); |
| |
| /* postblend setting */ |
| VSYNC_WR_MPEG_REG( |
| VPP_POSTBLEND_VD1_H_START_END + misc_off, |
| ((setting->postblend_h_start & vd_size_mask) |
| << VPP_VD1_START_BIT) | |
| ((setting->postblend_h_end & vd_size_mask) |
| << VPP_VD1_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_POSTBLEND_VD1_V_START_END + misc_off, |
| ((setting->postblend_v_start & vd_size_mask) |
| << VPP_VD1_START_BIT) | |
| ((setting->postblend_v_end & vd_size_mask) |
| << VPP_VD1_END_BIT)); |
| |
| if (!legacy_vpp) |
| VSYNC_WR_MPEG_REG( |
| VPP_MISC1 + misc_off, |
| setting->layer_alpha); |
| } |
| |
| static void vd2_blend_setting( |
| struct blend_setting_s *setting) |
| { |
| u32 misc_off; |
| u32 vd_size_mask = VPP_VD_SIZE_MASK; |
| |
| if (!setting) |
| return; |
| |
| /* g12a change to 13 bits */ |
| if (!legacy_vpp) |
| vd_size_mask = 0x1fff; |
| |
| misc_off = 0; |
| |
| /* vd2 preblend size should be same postblend size */ |
| /* preblend setting */ |
| VSYNC_WR_MPEG_REG( |
| VPP_BLEND_VD2_H_START_END + misc_off, |
| ((setting->postblend_h_start & vd_size_mask) |
| << VPP_VD1_START_BIT) | |
| ((setting->postblend_h_end & vd_size_mask) |
| << VPP_VD1_END_BIT)); |
| |
| VSYNC_WR_MPEG_REG( |
| VPP_BLEND_VD2_V_START_END + misc_off, |
| ((setting->postblend_v_start & vd_size_mask) |
| << VPP_VD1_START_BIT) | |
| ((setting->postblend_v_end & vd_size_mask) |
| << VPP_VD1_END_BIT)); |
| } |
| |
| static void proc_vd1_vsc_phase_per_vsync( |
| struct video_layer_s *layer, |
| struct vpp_frame_par_s *frame_par, |
| struct vframe_s *vf) |
| { |
| struct f2v_vphase_s *vphase; |
| u32 misc_off, vin_type; |
| struct vppfilter_mode_s *vpp_filter; |
| |
| if (!layer || !frame_par || !vf) |
| return; |
| |
| vpp_filter = &frame_par->vpp_filter; |
| misc_off = layer->misc_reg_offt; |
| vin_type = vf->type & VIDTYPE_TYPEMASK; |
| /* vertical phase */ |
| vphase = &frame_par->VPP_vf_ini_phase_ |
| [vpp_phase_table[vin_type] |
| [layer->vout_type]]; |
| VSYNC_WR_MPEG_REG( |
| VPP_VSC_INI_PHASE + misc_off, |
| ((u32)(vphase->phase) << 8)); |
| |
| if (vphase->repeat_skip >= 0) { |
| /* skip lines */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_VSC_PHASE_CTRL + misc_off, |
| skip_tab[vphase->repeat_skip], |
| VPP_PHASECTL_INIRCVNUMT_BIT, |
| VPP_PHASECTL_INIRCVNUM_WID + |
| VPP_PHASECTL_INIRPTNUM_WID); |
| } else { |
| /* repeat first line */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_VSC_PHASE_CTRL + misc_off, |
| 4, |
| VPP_PHASECTL_INIRCVNUMT_BIT, |
| VPP_PHASECTL_INIRCVNUM_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_VSC_PHASE_CTRL + misc_off, |
| 1 - vphase->repeat_skip, |
| VPP_PHASECTL_INIRPTNUMT_BIT, |
| VPP_PHASECTL_INIRPTNUM_WID); |
| } |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_VSC_PHASE_CTRL + misc_off, |
| (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, |
| VPP_PHASECTL_DOUBLELINE_BIT, |
| VPP_PHASECTL_DOUBLELINE_WID); |
| } |
| |
| static void proc_vd2_vsc_phase_per_vsync( |
| struct video_layer_s *layer, |
| struct vpp_frame_par_s *frame_par, |
| struct vframe_s *vf) |
| { |
| struct f2v_vphase_s *vphase; |
| u32 misc_off, vin_type; |
| struct vppfilter_mode_s *vpp_filter; |
| |
| if (!layer || !frame_par || !vf) |
| return; |
| |
| vpp_filter = &frame_par->vpp_filter; |
| misc_off = layer->misc_reg_offt; |
| vin_type = vf->type & VIDTYPE_TYPEMASK; |
| /* vertical phase */ |
| vphase = &frame_par->VPP_vf_ini_phase_ |
| [vpp_phase_table[vin_type] |
| [layer->vout_type]]; |
| VSYNC_WR_MPEG_REG( |
| VD2_VSC_INI_PHASE + misc_off, |
| ((u32)(vphase->phase) << 8)); |
| |
| if (vphase->repeat_skip >= 0) { |
| /* skip lines */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_VSC_PHASE_CTRL + misc_off, |
| skip_tab[vphase->repeat_skip], |
| VPP_PHASECTL_INIRCVNUMT_BIT, |
| VPP_PHASECTL_INIRCVNUM_WID + |
| VPP_PHASECTL_INIRPTNUM_WID); |
| } else { |
| /* repeat first line */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_VSC_PHASE_CTRL + misc_off, |
| 4, |
| VPP_PHASECTL_INIRCVNUMT_BIT, |
| VPP_PHASECTL_INIRCVNUM_WID); |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_VSC_PHASE_CTRL + misc_off, |
| 1 - vphase->repeat_skip, |
| VPP_PHASECTL_INIRPTNUMT_BIT, |
| VPP_PHASECTL_INIRPTNUM_WID); |
| } |
| |
| VSYNC_WR_MPEG_REG_BITS( |
| VD2_VSC_PHASE_CTRL + misc_off, |
| (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, |
| VPP_PHASECTL_DOUBLELINE_BIT, |
| VPP_PHASECTL_DOUBLELINE_WID); |
| } |
| |
| static void disable_vd1_blend(struct video_layer_s *layer) |
| { |
| u32 misc_off; |
| |
| if (!layer) |
| return; |
| misc_off = layer->misc_reg_offt; |
| if (layer->global_debug & DEBUG_FLAG_BLACKOUT) |
| pr_info("VIDEO: VD1 AFBC off now. dispbuf:%p, *dispbuf_mapping:%p, local: %p, %p, %p, %p\n", |
| layer->dispbuf, |
| layer->dispbuf_mapping ? |
| *layer->dispbuf_mapping : NULL, |
| &vf_local, &local_pip, |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL); |
| VSYNC_WR_MPEG_REG(layer->vd_afbc_reg.afbc_enable, 0); |
| VSYNC_WR_MPEG_REG(layer->vd_mif_reg.vd_if0_gen_reg, 0); |
| |
| if (is_dolby_vision_enable()) { |
| if (is_meson_txlx_cpu() || |
| is_meson_gxm_cpu()) |
| VSYNC_WR_MPEG_REG_BITS( |
| VIU_MISC_CTRL1 + misc_off, |
| 3, 16, 2); /* bypass core1 */ |
| else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) |
| VSYNC_WR_MPEG_REG_BITS( |
| DOLBY_PATH_CTRL + misc_off, |
| 3, 0, 2); |
| } |
| |
| /*auto disable sr when video off*/ |
| if (!is_meson_txl_cpu() && |
| !is_meson_txlx_cpu()) { |
| VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0); |
| VSYNC_WR_MPEG_REG(VPP_SRSHARP1_CTRL, 0); |
| } |
| |
| if (layer->dispbuf && |
| is_local_vf(layer->dispbuf)) |
| layer->dispbuf = NULL; |
| if (layer->dispbuf_mapping) { |
| if (*layer->dispbuf_mapping && |
| is_local_vf(*layer->dispbuf_mapping)) |
| *layer->dispbuf_mapping = NULL; |
| layer->dispbuf_mapping = NULL; |
| layer->dispbuf = NULL; |
| } |
| layer->new_vframe_count = 0; |
| } |
| |
| static void disable_vd2_blend(struct video_layer_s *layer) |
| { |
| if (!layer) |
| return; |
| |
| if (layer->global_debug & DEBUG_FLAG_BLACKOUT) |
| pr_info("VIDEO: VD2 AFBC off now. dispbuf:%p, *dispbuf_mapping:%p, local: %p, %p, %p, %p\n", |
| layer->dispbuf, |
| layer->dispbuf_mapping ? |
| *layer->dispbuf_mapping : NULL, |
| &vf_local, &local_pip, |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL); |
| VSYNC_WR_MPEG_REG(layer->vd_afbc_reg.afbc_enable, 0); |
| VSYNC_WR_MPEG_REG(layer->vd_mif_reg.vd_if0_gen_reg, 0); |
| |
| if (layer->dispbuf && |
| is_local_vf(layer->dispbuf)) |
| layer->dispbuf = NULL; |
| if (layer->dispbuf_mapping) { |
| if (*layer->dispbuf_mapping && |
| is_local_vf(*layer->dispbuf_mapping)) |
| *layer->dispbuf_mapping = NULL; |
| layer->dispbuf_mapping = NULL; |
| layer->dispbuf = NULL; |
| } |
| /* FIXME: remove global variables */ |
| last_el_status = 0; |
| need_disable_vd2 = false; |
| layer->new_vframe_count = 0; |
| } |
| |
| static void vd1_clip_setting(struct clip_setting_s *setting) |
| { |
| u32 misc_off; |
| |
| if (!setting) |
| return; |
| |
| misc_off = setting->misc_reg_offt; |
| VSYNC_WR_MPEG_REG( |
| VPP_VD1_CLIP_MISC0 + misc_off, |
| setting->clip_max); |
| VSYNC_WR_MPEG_REG( |
| VPP_VD1_CLIP_MISC1 + misc_off, |
| setting->clip_min); |
| } |
| |
| static void vd2_clip_setting(struct clip_setting_s *setting) |
| { |
| u32 misc_off; |
| |
| if (!setting) |
| return; |
| |
| misc_off = setting->misc_reg_offt; |
| VSYNC_WR_MPEG_REG( |
| VPP_VD2_CLIP_MISC0 + misc_off, |
| setting->clip_max); |
| VSYNC_WR_MPEG_REG( |
| VPP_VD2_CLIP_MISC1 + misc_off, |
| setting->clip_min); |
| } |
| |
| /********************************************************* |
| * DV EL APIs |
| *********************************************************/ |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| static bool is_sc_enable_before_pps(struct vpp_frame_par_s *par) |
| { |
| bool ret = false; |
| |
| if (par) { |
| if (par->supsc0_enable && |
| ((par->supscl_path == CORE0_PPS_CORE1) || |
| (par->supscl_path == CORE0_BEFORE_PPS))) |
| ret = true; |
| else if (par->supsc1_enable && |
| (par->supscl_path == CORE1_BEFORE_PPS)) |
| ret = true; |
| else if ((par->supsc0_enable || par->supsc1_enable) && |
| (par->supscl_path == CORE0_CORE1_PPS)) |
| ret = true; |
| } |
| return ret; |
| } |
| |
| void correct_vd1_mif_size_for_DV( |
| struct vpp_frame_par_s *par, struct vframe_s *el_vf) |
| { |
| u32 aligned_mask = 0xfffffffe; |
| u32 old_len; |
| |
| if ((is_dolby_vision_on() == true) && |
| (par->VPP_line_in_length_ > 0) && |
| !is_sc_enable_before_pps(par)) { |
| /* work around to skip the size check when sc enable */ |
| if (el_vf) { |
| /* |
| *if (cur_dispbuf2->type |
| * & VIDTYPE_COMPRESS) |
| * aligned_mask = 0xffffffc0; |
| *else |
| */ |
| aligned_mask = 0xfffffffc; |
| } |
| #ifdef CHECK_LATER /* def TV_REVERSE */ |
| if (reverse) { |
| par->VPP_line_in_length_ |
| &= 0xfffffffe; |
| par->VPP_hd_end_lines_ |
| &= 0xfffffffe; |
| par->VPP_hd_start_lines_ = |
| par->VPP_hd_end_lines_ + 1 |
| - (par->VPP_line_in_length_ << |
| par->hscale_skip_count); |
| } else |
| #endif |
| { |
| par->VPP_line_in_length_ |
| &= aligned_mask; |
| par->VPP_hd_start_lines_ |
| &= aligned_mask; |
| par->VPP_hd_end_lines_ = |
| par->VPP_hd_start_lines_ + |
| (par->VPP_line_in_length_ << |
| par->hscale_skip_count) - 1; |
| /* if have el layer, need 2 pixel align by height */ |
| if (el_vf) { |
| old_len = |
| par->VPP_vd_end_lines_ - |
| par->VPP_vd_start_lines_ + 1; |
| if (old_len & 1) |
| par->VPP_vd_end_lines_--; |
| if (par->VPP_vd_start_lines_ & 1) { |
| par->VPP_vd_start_lines_--; |
| par->VPP_vd_end_lines_--; |
| } |
| old_len = |
| par->VPP_vd_end_lines_ - |
| par->VPP_vd_start_lines_ + 1; |
| old_len = old_len >> par->vscale_skip_count; |
| if (par->VPP_pic_in_height_ < old_len) |
| par->VPP_pic_in_height_ = old_len; |
| } |
| } |
| } |
| } |
| |
| void config_dvel_position( |
| struct video_layer_s *layer, |
| struct mif_pos_s *setting, |
| struct vframe_s *el_vf) |
| { |
| int width_bl, width_el; |
| int height_bl, height_el; |
| int shift = 0, line_in_length; |
| struct vpp_frame_par_s *cur_frame_par; |
| struct vframe_s *bl_vf; |
| |
| if (!layer || !layer->cur_frame_par || |
| !layer->dispbuf || !setting || !el_vf) |
| return; |
| |
| bl_vf = layer->dispbuf; |
| cur_frame_par = layer->cur_frame_par; |
| |
| setting->id = 1; |
| setting->p_vd_mif_reg = &vd_layer[1].vd_mif_reg; |
| setting->p_vd_afbc_reg = &vd_layer[1].vd_afbc_reg; |
| setting->reverse = glayer_info[0].reverse; |
| |
| width_el = (el_vf->type & VIDTYPE_COMPRESS) ? |
| el_vf->compWidth : el_vf->width; |
| if (!(el_vf->type & VIDTYPE_VD2)) { |
| width_bl = |
| (bl_vf->type & VIDTYPE_COMPRESS) ? |
| bl_vf->compWidth : bl_vf->width; |
| if (width_el >= width_bl) |
| width_el = width_bl; |
| else if (width_el != width_bl / 2) |
| width_el = width_bl / 2; |
| if (width_el >= width_bl) |
| shift = 0; |
| else |
| shift = 1; |
| } |
| |
| height_el = (el_vf->type & VIDTYPE_COMPRESS) ? |
| el_vf->compHeight : el_vf->height; |
| if (!(el_vf->type & VIDTYPE_VD2)) { |
| height_bl = |
| (bl_vf->type & VIDTYPE_COMPRESS) ? |
| bl_vf->compHeight : bl_vf->height; |
| if (height_el >= height_bl) |
| height_el = height_bl; |
| else if (height_el != height_bl / 2) |
| height_el = height_bl / 2; |
| } |
| |
| setting->src_w = width_el; |
| setting->src_h = height_el; |
| |
| setting->start_x_lines = 0; |
| setting->end_x_lines = width_el - 1; |
| setting->start_y_lines = 0; |
| setting->end_y_lines = height_el - 1; |
| |
| if ((is_dolby_vision_on() == true) && |
| (cur_frame_par->VPP_line_in_length_ > 0) && |
| !is_sc_enable_before_pps(cur_frame_par)) { |
| setting->start_x_lines = |
| cur_frame_par->VPP_hd_start_lines_ >> shift; |
| line_in_length = |
| cur_frame_par->VPP_line_in_length_ >> shift; |
| line_in_length &= 0xfffffffe; |
| if (line_in_length > 1) |
| setting->end_x_lines = |
| setting->start_x_lines + |
| line_in_length - 1; |
| else |
| setting->end_x_lines = setting->start_x_lines; |
| |
| setting->start_y_lines = |
| cur_frame_par->VPP_vd_start_lines_ >> shift; |
| if (setting->start_y_lines >= setting->end_y_lines) |
| setting->end_y_lines = setting->start_y_lines; |
| /* FIXME: if el len is 0, need disable bl */ |
| } |
| |
| setting->h_skip = layer->cur_frame_par->hscale_skip_count; |
| setting->v_skip = layer->cur_frame_par->vscale_skip_count; |
| /* afbc is nv12 as default */ |
| setting->hc_skip = 2; |
| setting->vc_skip = 2; |
| |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if ((layer->dispbuf->type |
| & VIDTYPE_VIU_444) || |
| (layer->dispbuf->type |
| & VIDTYPE_RGB_444)) { |
| setting->hc_skip = 1; |
| setting->vc_skip = 1; |
| } else if (layer->dispbuf->type |
| & VIDTYPE_VIU_422) { |
| setting->vc_skip = 1; |
| } |
| } |
| |
| if ((layer->dispbuf->type & VIDTYPE_COMPRESS) && |
| !layer->cur_frame_par->nocomp) |
| setting->skip_afbc = false; |
| else |
| setting->skip_afbc = true; |
| |
| setting->l_hs_luma = setting->start_x_lines; |
| setting->l_he_luma = setting->end_x_lines; |
| setting->l_vs_luma = setting->start_y_lines; |
| setting->l_ve_luma = setting->end_y_lines; |
| setting->r_hs_luma = setting->start_x_lines; |
| setting->r_he_luma = setting->end_x_lines; |
| setting->r_vs_luma = setting->start_y_lines; |
| setting->r_ve_luma = setting->end_y_lines; |
| |
| setting->l_hs_chrm = setting->l_hs_luma >> 1; |
| setting->l_he_chrm = setting->l_he_luma >> 1; |
| setting->r_hs_chrm = setting->r_hs_luma >> 1; |
| setting->r_he_chrm = setting->r_he_luma >> 1; |
| setting->l_vs_chrm = setting->l_vs_luma >> 1; |
| setting->l_ve_chrm = setting->l_ve_luma >> 1; |
| setting->r_vs_chrm = setting->r_vs_luma >> 1; |
| setting->r_ve_chrm = setting->r_ve_luma >> 1; |
| setting->vpp_3d_mode = 0; |
| } |
| |
| s32 config_dvel_pps( |
| struct video_layer_s *layer, |
| struct scaler_setting_s *setting, |
| const struct vinfo_s *info) |
| { |
| if (!layer || !layer->cur_frame_par || |
| !setting || !info) |
| return -1; |
| |
| setting->support = |
| glayer_info[1].pps_support; |
| setting->frame_par = layer->cur_frame_par; |
| setting->id = 1; |
| setting->misc_reg_offt = vd_layer[1].misc_reg_offt; |
| |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) |
| setting->last_line_fix = true; |
| else |
| setting->last_line_fix = false; |
| |
| setting->sc_top_enable = false; |
| |
| setting->vinfo_width = info->width; |
| setting->vinfo_height = info->height; |
| return 0; |
| } |
| |
| s32 config_dvel_blend( |
| struct video_layer_s *layer, |
| struct blend_setting_s *setting, |
| struct vframe_s *dvel_vf) |
| { |
| if (!layer || !layer->cur_frame_par || !setting) |
| return -1; |
| |
| setting->frame_par = layer->cur_frame_par; |
| setting->id = 1; |
| setting->misc_reg_offt = vd_layer[1].misc_reg_offt; |
| setting->layer_alpha = layer->layer_alpha; |
| |
| setting->postblend_h_start = 0; |
| setting->postblend_h_end = |
| ((dvel_vf->type & VIDTYPE_COMPRESS) ? |
| dvel_vf->compWidth : |
| dvel_vf->width) - 1; |
| setting->postblend_v_start = 0; |
| setting->postblend_v_end = |
| ((dvel_vf->type & VIDTYPE_COMPRESS) ? |
| dvel_vf->compHeight : |
| dvel_vf->height) - 1; |
| return 0; |
| } |
| #endif |
| |
| /********************************************************* |
| * 3D APIs |
| *********************************************************/ |
| #ifdef TV_3D_FUNCTION_OPEN |
| static void get_3d_horz_pos( |
| struct video_layer_s *layer, |
| struct vframe_s *vf, u32 vpp_3d_mode, |
| u32 *ls, u32 *le, u32 *rs, u32 *re) |
| { |
| u32 crop_sx, crop_ex; |
| int frame_width; |
| struct disp_info_s *info = &glayer_info[0]; |
| |
| if (!vf) |
| return; |
| |
| crop_sx = info->crop_left; |
| crop_ex = info->crop_right; |
| |
| if (vf->type & VIDTYPE_COMPRESS) |
| frame_width = vf->compWidth; |
| else |
| frame_width = vf->width; |
| |
| if (vpp_3d_mode == VPP_3D_MODE_LR) { |
| /*half width, double height */ |
| *ls = layer->start_x_lines; |
| if (process_3d_type & MODE_3D_OUT_LR) |
| *le = layer->end_x_lines >> 1; |
| else |
| *le = layer->end_x_lines; |
| *rs = *ls + (frame_width >> 1); |
| *re = *le + (frame_width >> 1); |
| } else { |
| /* VPP_3D_MODE_TB: */ |
| /* VPP_3D_MODE_LA: */ |
| /* VPP_3D_MODE_FA: */ |
| /* and others. */ |
| if (vf->trans_fmt == TVIN_TFMT_3D_FP) { |
| *ls = vf->left_eye.start_x + crop_sx; |
| *le = vf->left_eye.start_x |
| + vf->left_eye.width |
| - crop_ex - 1; |
| *rs = vf->right_eye.start_x + crop_sx; |
| *re = vf->right_eye.start_x |
| + vf->right_eye.width |
| - crop_ex - 1; |
| } else if (process_3d_type |
| & MODE_3D_OUT_LR) { |
| *ls = layer->start_x_lines; |
| *le = layer->end_x_lines >> 1; |
| *rs = *ls; |
| *re = *le; |
| } else { |
| *ls = *rs = layer->start_x_lines; |
| *le = *re = layer->end_x_lines; |
| } |
| } |
| } |
| |
| static void get_3d_vert_pos( |
| struct video_layer_s *layer, |
| struct vframe_s *vf, u32 vpp_3d_mode, |
| u32 *ls, u32 *le, u32 *rs, u32 *re) |
| { |
| u32 crop_sy, crop_ey, height; |
| int frame_height; |
| struct disp_info_s *info = &glayer_info[0]; |
| |
| if (!vf) |
| return; |
| |
| crop_sy = info->crop_top; |
| crop_ey = info->crop_bottom; |
| |
| if (vf->type & VIDTYPE_COMPRESS) |
| frame_height = vf->compHeight; |
| else |
| frame_height = vf->height; |
| |
| if (vf->type & VIDTYPE_INTERLACE) |
| height = frame_height >> 1; |
| else |
| height = frame_height; |
| |
| if (vpp_3d_mode == VPP_3D_MODE_TB) { |
| if (vf->trans_fmt == TVIN_TFMT_3D_FP) { |
| *ls = vf->left_eye.start_y + (crop_sy >> 1); |
| *le = vf->left_eye.start_y |
| + vf->left_eye.height |
| - (crop_ey >> 1); |
| *rs = vf->right_eye.start_y + (crop_sy >> 1); |
| *re = vf->right_eye.start_y |
| + vf->left_eye.height |
| - (crop_ey >> 1); |
| if (vf->type & VIDTYPE_INTERLACE) { |
| /*if input is interlace vertical*/ |
| /*crop will be reduce by half */ |
| *ls = *ls >> 1; |
| *le = *le >> 1; |
| *rs = *rs >> 1; |
| *re = *re >> 1; |
| } |
| *le = *le - 1; |
| *re = *re - 1; |
| } else { |
| *ls = layer->start_y_lines >> 1; |
| *le = layer->end_y_lines >> 1; |
| if ((vf->type & VIDTYPE_VIU_FIELD) && |
| (vf->type & VIDTYPE_INTERLACE)) { |
| /* vdin interlace case */ |
| *rs = *ls + (height >> 1); |
| *re = *le + (height >> 1); |
| } else if (vf->type & VIDTYPE_INTERLACE) { |
| /* decode interlace case */ |
| *rs = *ls + height; |
| *re = *le + height; |
| } else { |
| /* mvc case: same width, same height */ |
| *rs = *ls + (height >> 1); |
| *re = *le + (height >> 1); |
| } |
| if ((process_3d_type |
| & MODE_3D_TO_2D_MASK) || |
| (process_3d_type |
| & MODE_3D_OUT_LR)) { |
| /* same width, half height */ |
| *ls = layer->start_y_lines; |
| *le = layer->end_y_lines; |
| *rs = *ls + (height >> 1); |
| *re = *le + (height >> 1); |
| } |
| } |
| } else if (vpp_3d_mode == VPP_3D_MODE_LR) { |
| if ((process_3d_type & MODE_3D_TO_2D_MASK) || |
| (process_3d_type & MODE_3D_OUT_LR)) { |
| /*half width ,same height */ |
| *ls = layer->start_y_lines; |
| *le = layer->end_y_lines; |
| *rs = layer->start_y_lines; |
| *re = layer->end_y_lines; |
| } else { |
| /* half width,double height */ |
| *ls = layer->start_y_lines >> 1; |
| *le = layer->end_y_lines >> 1; |
| *rs = layer->start_y_lines >> 1; |
| *re = layer->end_y_lines >> 1; |
| } |
| } else if (vpp_3d_mode == VPP_3D_MODE_FA) { |
| /*same width same heiht */ |
| if ((process_3d_type & MODE_3D_TO_2D_MASK) || |
| (process_3d_type & MODE_3D_OUT_LR)) { |
| *ls = layer->start_y_lines; |
| *le = layer->end_y_lines; |
| *rs = layer->start_y_lines; |
| *re = layer->end_y_lines; |
| } else { |
| *ls = (layer->start_y_lines + crop_sy) >> 1; |
| *le = (layer->end_y_lines + crop_ey) >> 1; |
| *rs = (layer->start_y_lines + crop_sy) >> 1; |
| *re = (layer->end_y_lines + crop_ey) >> 1; |
| } |
| } else if (vpp_3d_mode == VPP_3D_MODE_LA) { |
| if ((process_3d_type & MODE_3D_OUT_FA_MASK) || |
| (process_3d_type & MODE_3D_OUT_TB) || |
| (process_3d_type & MODE_3D_OUT_LR)) { |
| *rs = layer->start_y_lines + 1; |
| *ls = layer->start_y_lines; |
| } else if ((process_3d_type & MODE_3D_LR_SWITCH) || |
| (process_3d_type & MODE_3D_TO_2D_R)) { |
| *ls = layer->start_y_lines + 1; |
| *rs = layer->start_y_lines + 1; |
| } else { |
| *ls = layer->start_y_lines; |
| *rs = layer->start_y_lines; |
| } |
| *le = layer->end_y_lines; |
| *re = layer->end_y_lines; |
| } else { |
| *ls = layer->start_y_lines; |
| *le = layer->end_y_lines; |
| *rs = layer->start_y_lines; |
| *re = layer->end_y_lines; |
| } |
| } |
| |
| void config_3d_vd2_position( |
| struct video_layer_s *layer, |
| struct mif_pos_s *setting) |
| { |
| if (!layer || !layer->cur_frame_par || !layer->dispbuf || !setting) |
| return; |
| |
| memcpy(setting, &layer->mif_setting, sizeof(struct mif_pos_s)); |
| setting->id = 1; |
| setting->p_vd_mif_reg = &vd_layer[1].vd_mif_reg; |
| setting->p_vd_afbc_reg = &vd_layer[1].vd_afbc_reg; |
| |
| /* need not change the horz position */ |
| /* not framepacking mode, need process vert position more */ |
| /* framepacking mode, need use right eye position */ |
| /* to set vd2 Y0 not vd1 Y1*/ |
| if ((layer->dispbuf->type & VIDTYPE_MVC) && framepacking_support) { |
| setting->l_vs_chrm = |
| setting->r_vs_chrm; |
| setting->l_ve_chrm = |
| setting->r_ve_chrm; |
| setting->l_vs_luma = |
| setting->r_vs_luma; |
| setting->l_ve_luma = |
| setting->r_ve_luma; |
| setting->r_vs_luma = 0; |
| setting->r_ve_luma = 0; |
| setting->r_vs_chrm = 0; |
| setting->r_ve_chrm = 0; |
| } |
| setting->vpp_3d_mode = 0; |
| } |
| |
| s32 config_3d_vd2_pps( |
| struct video_layer_s *layer, |
| struct scaler_setting_s *setting, |
| const struct vinfo_s *info) |
| { |
| if (!layer || !layer->cur_frame_par || !setting || !info) |
| return -1; |
| |
| memcpy(setting, &layer->sc_setting, sizeof(struct scaler_setting_s)); |
| setting->support = glayer_info[1].pps_support; |
| setting->sc_top_enable = false; |
| setting->id = 1; |
| return 0; |
| } |
| |
| s32 config_3d_vd2_blend( |
| struct video_layer_s *layer, |
| struct blend_setting_s *setting) |
| { |
| struct vpp_frame_par_s *cur_frame_par; |
| u32 x_lines, y_lines; |
| |
| if (!layer || !layer->cur_frame_par || !setting) |
| return -1; |
| |
| memcpy(setting, &layer->bld_setting, sizeof(struct blend_setting_s)); |
| setting->id = 1; |
| |
| cur_frame_par = layer->cur_frame_par; |
| x_lines = layer->end_x_lines / |
| (cur_frame_par->hscale_skip_count + 1); |
| y_lines = layer->end_y_lines / |
| (cur_frame_par->vscale_skip_count + 1); |
| |
| if (process_3d_type & MODE_3D_OUT_TB) { |
| setting->postblend_h_start = |
| layer->start_x_lines; |
| setting->postblend_h_end = |
| layer->end_x_lines; |
| setting->postblend_v_start = |
| (y_lines + 1) >> 1; |
| setting->postblend_v_end = y_lines; |
| } else if (process_3d_type & MODE_3D_OUT_LR) { |
| /* vd1 and vd2 do pre blend */ |
| setting->postblend_h_start = |
| (x_lines + 1) >> 1; |
| setting->postblend_h_end = x_lines; |
| setting->postblend_v_start = |
| layer->start_y_lines; |
| setting->postblend_v_end = |
| layer->end_y_lines; |
| } else if (layer->dispbuf && |
| (layer->dispbuf->type & VIDTYPE_MVC)) { |
| u32 blank; |
| |
| if (framepacking_support) |
| blank = framepacking_blank; |
| else |
| blank = 0; |
| setting->postblend_v_start = |
| (cur_frame_par->VPP_vd_end_lines_ |
| - blank + 1) >> 1; |
| setting->postblend_v_start += blank; |
| setting->postblend_v_end = |
| cur_frame_par->VPP_vd_end_lines_; |
| setting->postblend_h_start = |
| cur_frame_par->VPP_hd_start_lines_; |
| setting->postblend_h_end = |
| cur_frame_par->VPP_hd_end_lines_; |
| } |
| return 0; |
| } |
| |
| void switch_3d_view_per_vsync( |
| struct video_layer_s *layer) |
| { |
| struct vpp_frame_par_s *cur_frame_par; |
| u32 misc_off; |
| u32 start_aligned, end_aligned, block_len; |
| u32 FA_enable = process_3d_type & MODE_3D_OUT_FA_MASK; |
| u32 src_start_x_lines, src_end_x_lines; |
| u32 src_start_y_lines, src_end_y_lines; |
| struct hw_vd_reg_s *vd_mif_reg; |
| struct hw_vd_reg_s *vd2_mif_reg; |
| struct hw_afbc_reg_s *vd_afbc_reg; |
| |
| if (!layer || !layer->cur_frame_par || !layer->dispbuf) |
| return; |
| |
| vd_mif_reg = &layer->vd_mif_reg; |
| vd2_mif_reg = &vd_layer[1].vd_mif_reg; |
| vd_afbc_reg = &layer->vd_afbc_reg; |
| |
| src_start_x_lines = 0; |
| src_end_x_lines = |
| ((layer->dispbuf->type & |
| VIDTYPE_COMPRESS) ? |
| layer->dispbuf->compWidth : |
| layer->dispbuf->width) - 1; |
| src_start_y_lines = 0; |
| src_end_y_lines = |
| ((layer->dispbuf->type & |
| VIDTYPE_COMPRESS) ? |
| layer->dispbuf->compHeight : |
| layer->dispbuf->height) - 1; |
| |
| misc_off = layer->misc_reg_offt; |
| cur_frame_par = layer->cur_frame_par; |
| if (FA_enable && (toggle_3d_fa_frame == OUT_FA_A_FRAME)) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_MISC + misc_off, 1, 14, 1); |
| /* VPP_VD1_PREBLEND disable */ |
| VSYNC_WR_MPEG_REG_BITS(VPP_MISC + |
| VPP_MISC + misc_off, 1, 10, 1); |
| /* VPP_VD1_POSTBLEND disable */ |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_psel, |
| 0x4000000); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_psel, |
| 0x4000000); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_psel, |
| 0x4000000); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_psel, |
| 0x4000000); |
| if (layer->dispbuf->type & VIDTYPE_COMPRESS) { |
| if ((process_3d_type & MODE_FORCE_3D_FA_LR) && |
| (cur_frame_par->vpp_3d_mode == 1)) { |
| start_aligned = src_start_x_lines; |
| end_aligned = src_end_x_lines + 1; |
| block_len = |
| (end_aligned - start_aligned) / 2; |
| block_len = block_len / |
| (cur_frame_par->hscale_skip_count + 1); |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_hor_scope, |
| (start_aligned << 16) | |
| (start_aligned + block_len - 1)); |
| } |
| if ((process_3d_type & MODE_FORCE_3D_FA_TB) && |
| (cur_frame_par->vpp_3d_mode == 2)) { |
| start_aligned = |
| round_down(src_start_y_lines, 4); |
| end_aligned = |
| round_up(src_end_y_lines + 1, 4); |
| block_len = end_aligned - start_aligned; |
| block_len = block_len / 8; |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| ((start_aligned / 4) << 16) | |
| ((start_aligned / 4) + block_len - 1)); |
| } |
| } |
| } else if (FA_enable && (toggle_3d_fa_frame == OUT_FA_B_FRAME)) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_MISC + misc_off, 1, 14, 1); |
| /* VPP_VD1_PREBLEND disable */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_MISC + misc_off, 1, 10, 1); |
| /* VPP_VD1_POSTBLEND disable */ |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_psel, 0); |
| if (layer->dispbuf->type & VIDTYPE_COMPRESS) { |
| if ((process_3d_type & MODE_FORCE_3D_FA_LR) && |
| (cur_frame_par->vpp_3d_mode == 1)) { |
| start_aligned = src_end_x_lines; |
| end_aligned = src_end_x_lines + 1; |
| block_len = |
| (end_aligned - start_aligned) / 2; |
| block_len = block_len / |
| (cur_frame_par->hscale_skip_count + 1); |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_pixel_hor_scope, |
| ((start_aligned + block_len) << 16) | |
| (end_aligned - 1)); |
| } |
| if ((process_3d_type & MODE_FORCE_3D_FA_TB) && |
| (cur_frame_par->vpp_3d_mode == 2)) { |
| start_aligned = |
| round_down(src_start_y_lines, 4); |
| end_aligned = |
| round_up(src_end_y_lines + 1, 4); |
| block_len = end_aligned - start_aligned; |
| block_len = block_len / 8; |
| VSYNC_WR_MPEG_REG( |
| vd_afbc_reg->afbc_mif_ver_scope, |
| (((start_aligned / 4) + block_len) << 16) | |
| ((end_aligned / 4) - 1)); |
| } |
| } |
| } else if (FA_enable && (toggle_3d_fa_frame == OUT_FA_BANK_FRAME)) { |
| /* output a banking frame */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_MISC + misc_off, 0, 14, 1); |
| /* VPP_VD1_PREBLEND disable */ |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_MISC + misc_off, 0, 10, 1); |
| /* VPP_VD1_POSTBLEND disable */ |
| } |
| |
| if ((process_3d_type & MODE_3D_OUT_TB) || |
| (process_3d_type & MODE_3D_OUT_LR)) { |
| if (cur_frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) { |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_psel, |
| 0x4000000); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_psel, |
| 0x4000000); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_psel, 0); |
| } else { |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_luma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd_mif_reg->vd_if0_chroma_psel, 0); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_luma_psel, |
| 0x4000000); |
| VSYNC_WR_MPEG_REG( |
| vd2_mif_reg->vd_if0_chroma_psel, |
| 0x4000000); |
| } |
| } |
| |
| if (force_3d_scaler <= 3 && |
| cur_frame_par->vpp_3d_scale) { |
| VSYNC_WR_MPEG_REG_BITS( |
| VPP_VSC_PHASE_CTRL + misc_off, |
| force_3d_scaler, |
| VPP_PHASECTL_DOUBLELINE_BIT, |
| VPP_PHASECTL_DOUBLELINE_WID); |
| } |
| } |
| #endif |
| |
| s32 config_vd_position( |
| struct video_layer_s *layer, |
| struct mif_pos_s *setting) |
| { |
| if (!layer || !layer->cur_frame_par || !layer->dispbuf || !setting) |
| return -1; |
| |
| setting->id = layer->layer_id; |
| setting->p_vd_mif_reg = &layer->vd_mif_reg; |
| setting->p_vd_afbc_reg = &layer->vd_afbc_reg; |
| |
| setting->reverse = glayer_info[setting->id].reverse; |
| setting->src_w = |
| (layer->dispbuf->type & VIDTYPE_COMPRESS) ? |
| layer->dispbuf->compWidth : layer->dispbuf->width; |
| setting->src_h = |
| (layer->dispbuf->type & VIDTYPE_COMPRESS) ? |
| layer->dispbuf->compHeight : layer->dispbuf->height; |
| |
| setting->start_x_lines = layer->start_x_lines; |
| setting->end_x_lines = layer->end_x_lines; |
| setting->start_y_lines = layer->start_y_lines; |
| setting->end_y_lines = layer->end_y_lines; |
| |
| setting->h_skip = layer->cur_frame_par->hscale_skip_count; |
| setting->v_skip = layer->cur_frame_par->vscale_skip_count; |
| /* afbc is nv12 as default */ |
| setting->hc_skip = 2; |
| setting->vc_skip = 2; |
| |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| if ((layer->dispbuf->type |
| & VIDTYPE_VIU_444) || |
| (layer->dispbuf->type |
| & VIDTYPE_RGB_444)) { |
| setting->hc_skip = 1; |
| setting->vc_skip = 1; |
| } else if (layer->dispbuf->type |
| & VIDTYPE_VIU_422) { |
| setting->vc_skip = 1; |
| } |
| } |
| |
| if ((layer->dispbuf->type & VIDTYPE_COMPRESS) && |
| !layer->cur_frame_par->nocomp) |
| setting->skip_afbc = false; |
| else |
| setting->skip_afbc = true; |
| |
| setting->l_hs_luma = layer->start_x_lines; |
| setting->l_he_luma = layer->end_x_lines; |
| setting->l_vs_luma = layer->start_y_lines; |
| setting->l_ve_luma = layer->end_y_lines; |
| setting->r_hs_luma = layer->start_x_lines; |
| setting->r_he_luma = layer->end_x_lines; |
| setting->r_vs_luma = layer->start_y_lines; |
| setting->r_ve_luma = layer->end_y_lines; |
| |
| #ifdef TV_3D_FUNCTION_OPEN |
| if ((setting->id == 0) && |
| (process_3d_type & MODE_3D_ENABLE)) { |
| get_3d_horz_pos( |
| layer, layer->dispbuf, |
| layer->cur_frame_par->vpp_3d_mode, |
| &setting->l_hs_luma, &setting->l_he_luma, |
| &setting->r_hs_luma, &setting->r_he_luma); |
| get_3d_vert_pos( |
| layer, layer->dispbuf, |
| layer->cur_frame_par->vpp_3d_mode, |
| &setting->l_vs_luma, &setting->l_ve_luma, |
| &setting->r_vs_luma, &setting->r_ve_luma); |
| } |
| #endif |
| setting->l_hs_chrm = setting->l_hs_luma >> 1; |
| setting->l_he_chrm = setting->l_he_luma >> 1; |
| setting->r_hs_chrm = setting->r_hs_luma >> 1; |
| setting->r_he_chrm = setting->r_he_luma >> 1; |
| setting->l_vs_chrm = setting->l_vs_luma >> 1; |
| setting->l_ve_chrm = setting->l_ve_luma >> 1; |
| setting->r_vs_chrm = setting->r_vs_luma >> 1; |
| setting->r_ve_chrm = setting->r_ve_luma >> 1; |
| |
| #ifdef TV_3D_FUNCTION_OPEN |
| /* need not change the horz position */ |
| /* not framepacking mode, need process vert position more */ |
| /* framepacking mode, need use right eye position */ |
| /* to set vd2 Y0 not vd1 Y1*/ |
| if ((setting->id == 0) && |
| (layer->dispbuf->type & VIDTYPE_MVC) && |
| !framepacking_support) { |
| setting->l_vs_chrm = |
| setting->l_vs_luma; |
| setting->l_ve_chrm = |
| setting->l_ve_luma - 1; |
| setting->l_vs_luma *= 2; |
| setting->l_ve_luma = |
| setting->l_ve_luma * 2 - 1; |
| setting->r_vs_luma = 0; |
| setting->r_ve_luma = 0; |
| setting->r_vs_chrm = 0; |
| setting->r_ve_chrm = 0; |
| } |
| #endif |
| setting->vpp_3d_mode = |
| layer->cur_frame_par->vpp_3d_mode; |
| return 0; |
| } |
| |
| s32 config_vd_pps( |
| struct video_layer_s *layer, |
| struct scaler_setting_s *setting, |
| const struct vinfo_s *info) |
| { |
| struct vppfilter_mode_s *vpp_filter; |
| struct vpp_frame_par_s *cur_frame_par; |
| |
| if (!layer || !layer->cur_frame_par || !setting || !info) |
| return -1; |
| |
| setting->support = glayer_info[layer->layer_id].pps_support; |
| cur_frame_par = layer->cur_frame_par; |
| vpp_filter = &cur_frame_par->vpp_filter; |
| setting->frame_par = cur_frame_par; |
| setting->id = layer->layer_id; |
| setting->misc_reg_offt = layer->misc_reg_offt; |
| /* enable pps as default */ |
| setting->sc_top_enable = true; |
| setting->sc_h_enable = true; |
| setting->sc_v_enable = true; |
| setting->force_disable_sr = 0; |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) |
| setting->last_line_fix = true; |
| else |
| setting->last_line_fix = false; |
| |
| if ((vpp_filter->vpp_hsc_start_phase_step == 0x1000000) && |
| (vpp_filter->vpp_vsc_start_phase_step == 0x1000000) && |
| (vpp_filter->vpp_hsc_start_phase_step == |
| vpp_filter->vpp_hf_start_phase_step) && |
| !vpp_filter->vpp_pre_vsc_en && |
| !vpp_filter->vpp_pre_hsc_en && |
| layer->bypass_pps) |
| setting->sc_top_enable = false; |
| |
| if (setting->id == 0 && layer->dispbuf) { |
| if ((layer->dispbuf->width >= disable_sr_threshold) || |
| ((layer->dispbuf->type & VIDTYPE_COMPRESS) && |
| (layer->dispbuf->compWidth >= disable_sr_threshold))) |
| setting->force_disable_sr = 1; |
| } |
| setting->vinfo_width = info->width; |
| setting->vinfo_height = info->height; |
| return 0; |
| } |
| |
| s32 config_vd_blend( |
| struct video_layer_s *layer, |
| struct blend_setting_s *setting) |
| { |
| struct vpp_frame_par_s *cur_frame_par; |
| u32 x_lines, y_lines; |
| #ifdef CHECK_LATER |
| u32 type = 0; |
| #endif |
| |
| if (!layer || !layer->cur_frame_par || !setting) |
| return -1; |
| |
| cur_frame_par = layer->cur_frame_par; |
| setting->frame_par = cur_frame_par; |
| setting->id = layer->layer_id; |
| setting->misc_reg_offt = layer->misc_reg_offt; |
| setting->layer_alpha = layer->layer_alpha; |
| x_lines = layer->end_x_lines / |
| (cur_frame_par->hscale_skip_count + 1); |
| y_lines = layer->end_y_lines / |
| (cur_frame_par->vscale_skip_count + 1); |
| |
| if (legacy_vpp) { |
| setting->preblend_h_start = 0; |
| setting->preblend_h_end = 4096; |
| } else { |
| setting->preblend_h_start = 0; |
| setting->preblend_h_end = |
| cur_frame_par->video_input_w - 1; |
| } |
| if (layer->dispbuf && |
| (layer->dispbuf->type & VIDTYPE_MVC)) { |
| setting->preblend_v_start = |
| cur_frame_par->VPP_vd_start_lines_; |
| setting->preblend_v_end = y_lines; |
| setting->preblend_h_start = |
| cur_frame_par->VPP_hd_start_lines_; |
| setting->preblend_h_end = |
| cur_frame_par->VPP_hd_end_lines_; |
| } |
| |
| if ((cur_frame_par->VPP_post_blend_vd_v_end_ - |
| cur_frame_par->VPP_post_blend_vd_v_start_ + 1) |
| > VPP_PREBLEND_VD_V_END_LIMIT) { |
| setting->preblend_v_start = |
| cur_frame_par->VPP_post_blend_vd_v_start_; |
| setting->preblend_v_end = |
| cur_frame_par->VPP_post_blend_vd_v_end_; |
| } else { |
| setting->preblend_v_start = 0; |
| setting->preblend_v_end = |
| VPP_PREBLEND_VD_V_END_LIMIT - 1; |
| } |
| |
| setting->preblend_h_size = |
| cur_frame_par->video_input_w; |
| setting->postblend_h_size = |
| cur_frame_par->VPP_post_blend_h_size_; |
| |
| /* no scaler, so only can use mif setting */ |
| if (!glayer_info[layer->layer_id].pps_support) { |
| setting->postblend_h_start = |
| cur_frame_par->VPP_hd_start_lines_; |
| setting->postblend_h_end = |
| cur_frame_par->VPP_hd_start_lines_ + |
| cur_frame_par->video_input_w - 1; |
| setting->postblend_v_start = |
| cur_frame_par->VPP_vd_start_lines_; |
| setting->postblend_v_end = |
| cur_frame_par->VPP_vd_start_lines_ + |
| cur_frame_par->video_input_h - 1; |
| } else { |
| /* FIXME: use sr output */ |
| setting->postblend_h_start = |
| cur_frame_par->VPP_hsc_startp; |
| setting->postblend_h_end = |
| cur_frame_par->VPP_hsc_endp; |
| setting->postblend_v_start = |
| cur_frame_par->VPP_vsc_startp; |
| setting->postblend_v_end = |
| cur_frame_par->VPP_vsc_endp; |
| } |
| |
| if (!legacy_vpp) { |
| u32 temp_h = cur_frame_par->video_input_h; |
| |
| temp_h <<= 16; |
| setting->preblend_h_size |= temp_h; |
| |
| temp_h = |
| cur_frame_par->VPP_post_blend_vd_v_end_ + 1; |
| temp_h <<= 16; |
| setting->postblend_h_size |= temp_h; |
| } |
| #ifdef TV_3D_FUNCTION_OPEN |
| if (setting->id == 0) { |
| if (process_3d_type & MODE_3D_OUT_TB) { |
| setting->preblend_h_start = |
| cur_frame_par->VPP_hd_start_lines_; |
| setting->preblend_h_end = |
| cur_frame_par->VPP_hd_end_lines_; |
| setting->preblend_v_start = |
| cur_frame_par->VPP_vd_start_lines_; |
| setting->preblend_v_end = y_lines >> 1; |
| } else if (process_3d_type & MODE_3D_OUT_LR) { |
| /* vd1 and vd2 do pre blend */ |
| setting->preblend_h_start = |
| cur_frame_par->VPP_hd_start_lines_; |
| setting->preblend_h_end = x_lines >> 1; |
| setting->preblend_v_start = |
| cur_frame_par->VPP_vd_start_lines_; |
| setting->preblend_v_end = |
| cur_frame_par->VPP_vd_end_lines_; |
| } |
| } |
| #endif |
| /* FIXME: need remove this work around check for afbc */ |
| #ifdef CHECK_LATER |
| if (layer->dispbuf) |
| type = layer->dispbuf->type; |
| if (cur_frame_par->nocomp) |
| type &= ~VIDTYPE_COMPRESS; |
| |
| if (type & VIDTYPE_COMPRESS) { |
| u32 v_phase; |
| struct vppfilter_mode_s *vpp_filter = |
| &cur_frame_par->vpp_filter; |
| |
| v_phase = vpp_filter->vpp_vsc_start_phase_step; |
| v_phase *= (cur_frame_par->vscale_skip_count + 1); |
| if ((v_phase > 0x1000000) && |
| (glayer_info[setting->id].layer_top < 0)) { |
| if ((cur_frame_par->VPP_vsc_endp > 0x6) && |
| ((cur_frame_par->VPP_vsc_endp < 0x250) || |
| (cur_frame_par->VPP_vsc_endp < |
| cur_frame_par->VPP_post_blend_vd_v_end_ / 2))) { |
| setting->postblend_v_end -= 6; |
| } |
| } |
| } |
| #endif |
| return 0; |
| } |
| |
| void vd_set_dcu( |
| u8 layer_id, |
| struct video_layer_s *layer, |
| struct vpp_frame_par_s *frame_par, |
| struct vframe_s *vf) |
| { |
| if (layer_id == 0) |
| vd1_set_dcu(layer, frame_par, vf); |
| else |
| vd2_set_dcu(layer, frame_par, vf); |
| } |
| |
| void vd_mif_setting( |
| u8 layer_id, |
| struct mif_pos_s *setting) |
| { |
| if (layer_id == 0) |
| vd1_mif_setting(setting); |
| else |
| vd2_mif_setting(setting); |
| } |
| |
| void vd_scaler_setting( |
| u8 layer_id, |
| struct scaler_setting_s *setting) |
| { |
| if (setting && !setting->support) |
| return; |
| |
| if (layer_id == 0) |
| vd1_scaler_setting(setting); |
| else |
| vd2_scaler_setting(setting); |
| } |
| |
| void vd_blend_setting( |
| u8 layer_id, |
| struct blend_setting_s *setting) |
| { |
| if (layer_id == 0) |
| vd1_blend_setting(setting); |
| else |
| vd2_blend_setting(setting); |
| } |
| |
| void vd_clip_setting( |
| u8 layer_id, |
| struct clip_setting_s *setting) |
| { |
| if (setting->clip_done) |
| return; |
| |
| if (layer_id == 0) |
| vd1_clip_setting(setting); |
| else |
| vd2_clip_setting(setting); |
| setting->clip_done = true; |
| } |
| |
| void proc_vd_vsc_phase_per_vsync( |
| u8 layer_id, |
| struct video_layer_s *layer, |
| struct vpp_frame_par_s *frame_par, |
| struct vframe_s *vf) |
| { |
| if (!glayer_info[layer_id].pps_support) |
| return; |
| if (layer_id == 0) |
| proc_vd1_vsc_phase_per_vsync( |
| layer, frame_par, vf); |
| else |
| proc_vd2_vsc_phase_per_vsync( |
| layer, frame_par, vf); |
| } |
| |
| /********************************************************* |
| * Vpp APIs |
| *********************************************************/ |
| void set_video_mute(bool on) |
| { |
| video_mute_on = on; |
| } |
| EXPORT_SYMBOL(set_video_mute); |
| |
| int get_video_mute(void) |
| { |
| return video_mute_status; |
| } |
| EXPORT_SYMBOL(get_video_mute); |
| |
| static void check_video_mute(void) |
| { |
| u32 black_val; |
| |
| if (is_meson_tl1_cpu()) |
| black_val = (0x0 << 20) | (0x0 << 10) | 0; /* RGB */ |
| else |
| black_val = |
| (0x0 << 20) | (0x200 << 10) | 0x200; /* YUV */ |
| |
| if (video_mute_on) { |
| if (is_dolby_vision_on()) { |
| /* core 3 black */ |
| if (video_mute_status != VIDEO_MUTE_ON_DV) { |
| dolby_vision_set_toggle_flag(1); |
| pr_info("DOLBY: check_video_mute: VIDEO_MUTE_ON_DV\n"); |
| } |
| video_mute_status = VIDEO_MUTE_ON_DV; |
| } else { |
| if (video_mute_status != VIDEO_MUTE_ON_VPP) { |
| /* vpp black */ |
| VSYNC_WR_MPEG_REG( |
| VPP_CLIP_MISC0, |
| black_val); |
| VSYNC_WR_MPEG_REG( |
| VPP_CLIP_MISC1, |
| black_val); |
| WRITE_VCBUS_REG( |
| VPP_CLIP_MISC0, |
| black_val); |
| WRITE_VCBUS_REG( |
| VPP_CLIP_MISC1, |
| black_val); |
| pr_info("DOLBY: check_video_mute: VIDEO_MUTE_ON_VPP\n"); |
| } |
| video_mute_status = VIDEO_MUTE_ON_VPP; |
| } |
| } else { |
| if (is_dolby_vision_on()) { |
| if (video_mute_status != VIDEO_MUTE_OFF) { |
| dolby_vision_set_toggle_flag(2); |
| pr_info("DOLBY: check_video_mute: VIDEO_MUTE_OFF dv on\n"); |
| } |
| video_mute_status = VIDEO_MUTE_OFF; |
| } else { |
| if (video_mute_status != VIDEO_MUTE_OFF) { |
| VSYNC_WR_MPEG_REG( |
| VPP_CLIP_MISC0, |
| (0x3ff << 20) | |
| (0x3ff << 10) | |
| 0x3ff); |
| VSYNC_WR_MPEG_REG( |
| VPP_CLIP_MISC1, |
| (0x0 << 20) | |
| (0x0 << 10) | 0x0); |
| pr_info("DOLBY: check_video_mute: VIDEO_MUTE_OFF dv off\n"); |
| } |
| video_mute_status = VIDEO_MUTE_OFF; |
| } |
| } |
| } |
| |
| static int vpp_zorder_check(void) |
| { |
| int force_flush = 0; |
| u32 layer0_sel = 0; /* vd1 */ |
| u32 layer1_sel = 1; /* vd2 */ |
| |
| if (legacy_vpp) |
| return 0; |
| |
| if (glayer_info[1].zorder < glayer_info[0].zorder) { |
| layer0_sel = 1; |
| layer1_sel = 0; |
| if ((glayer_info[0].zorder >= reference_zorder) && |
| (glayer_info[1].zorder < reference_zorder)) |
| layer0_sel++; |
| } else { |
| layer0_sel = 0; |
| layer1_sel = 1; |
| if ((glayer_info[1].zorder >= reference_zorder) && |
| (glayer_info[0].zorder < reference_zorder)) |
| layer1_sel++; |
| } |
| if ((glayer_info[0].zorder >= reference_zorder) && |
| (glayer_info[1].zorder >= reference_zorder)) { |
| if (vd_layer[0].enabled && vd_layer[1].enabled) { |
| if (glayer_info[1].zorder < glayer_info[0].zorder) { |
| layer0_sel = 1; |
| layer1_sel = 0; |
| } else { |
| layer0_sel = 0; |
| layer1_sel = 1; |
| } |
| } else if (vd_layer[0].enabled) { |
| layer0_sel = 2; |
| layer1_sel = 0; |
| } else if (vd_layer[1].enabled) { |
| layer0_sel = 0; |
| layer1_sel = 2; |
| } |
| } |
| |
| glayer_info[0].cur_sel_port = layer0_sel; |
| glayer_info[1].cur_sel_port = layer1_sel; |
| |
| if ((glayer_info[0].cur_sel_port != glayer_info[0].last_sel_port) || |
| (glayer_info[1].cur_sel_port != glayer_info[1].last_sel_port)) { |
| force_flush = 1; |
| glayer_info[0].last_sel_port = glayer_info[0].cur_sel_port; |
| glayer_info[1].last_sel_port = glayer_info[1].cur_sel_port; |
| } |
| return force_flush; |
| } |
| |
| static void post_blend_dummy_data_update(void) |
| { |
| u32 bg_color; |
| |
| if (vd_layer[0].enabled) |
| bg_color = vd_layer[0].video_en_bg_color; |
| else |
| bg_color = vd_layer[0].video_dis_bg_color; |
| |
| /* for channel background setting |
| * no auto flag, return |
| */ |
| if (!(bg_color & VIDEO_AUTO_POST_BLEND_DUMMY)) |
| return; |
| |
| if (!legacy_vpp) |
| VSYNC_WR_MPEG_REG(VPP_POST_BLEND_BLEND_DUMMY_DATA, |
| bg_color & 0x00ffffff); |
| else |
| VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, |
| bg_color & 0x00ffffff); |
| } |
| |
| void vpp_blend_update( |
| const struct vinfo_s *vinfo) |
| { |
| u32 vpp_misc_save, vpp_misc_set, mode = 0; |
| u32 vpp_off = cur_dev->vpp_off; |
| int video1_off_req = 0; |
| int video2_off_req = 0; |
| unsigned long flags; |
| struct vpp_frame_par_s *vd1_frame_par = |
| vd_layer[0].cur_frame_par; |
| bool force_flush = false; |
| |
| check_video_mute(); |
| |
| if (vd_layer[0].enable_3d_mode == mode_3d_mvc_enable) |
| mode |= COMPOSE_MODE_3D; |
| else if (is_dolby_vision_on() && last_el_status) |
| mode |= COMPOSE_MODE_DV; |
| if (bypass_cm) |
| mode |= COMPOSE_MODE_BYPASS_CM; |
| |
| /* check the vpp post size first */ |
| if (!legacy_vpp && vinfo) { |
| u32 read_value = VSYNC_RD_MPEG_REG( |
| VPP_POSTBLEND_H_SIZE + vpp_off); |
| if (((vinfo->field_height << 16) | vinfo->width) |
| != read_value) |
| VSYNC_WR_MPEG_REG( |
| VPP_POSTBLEND_H_SIZE + vpp_off, |
| ((vinfo->field_height << 16) | vinfo->width)); |
| VSYNC_WR_MPEG_REG( |
| VPP_OUT_H_V_SIZE + vpp_off, |
| vinfo->width << 16 | |
| vinfo->field_height); |
| } else if (vinfo) { |
| if (VSYNC_RD_MPEG_REG( |
| VPP_POSTBLEND_H_SIZE + vpp_off) |
| != vinfo->width) |
| VSYNC_WR_MPEG_REG( |
| VPP_POSTBLEND_H_SIZE + vpp_off, |
| vinfo->width); |
| VSYNC_WR_MPEG_REG( |
| VPP_OUT_H_V_SIZE + vpp_off, |
| vinfo->width << 16 | |
| vinfo->field_height); |
| } |
| |
| vpp_misc_save = READ_VCBUS_REG(VPP_MISC + vpp_off); |
| |
| vpp_misc_set = vpp_misc_save; |
| if (is_dolby_vision_on()) |
| vpp_misc_set &= ~VPP_CM_ENABLE; |
| else if (mode & COMPOSE_MODE_BYPASS_CM) |
| vpp_misc_set &= ~VPP_CM_ENABLE; |
| else |
| vpp_misc_set |= VPP_CM_ENABLE; |
| |
| if (update_osd_vpp_misc && legacy_vpp) { |
| vpp_misc_set &= ~osd_vpp_misc_mask; |
| vpp_misc_set |= |
| (osd_vpp_misc & osd_vpp_misc_mask); |
| if (vpp_misc_set & |
| (VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND)) |
| vpp_misc_set |= VPP_POSTBLEND_EN; |
| } |
| if (likely(vd_layer[0].onoff_state != VIDEO_ENABLE_STATE_IDLE)) { |
| /* state change for video layer enable/disable */ |
| spin_lock_irqsave(&video_onoff_lock, flags); |
| if (vd_layer[0].onoff_state == VIDEO_ENABLE_STATE_ON_REQ) { |
| /* |
| * the video layer is enabled one vsync later,assumming |
| * all registers are ready from RDMA. |
| */ |
| vd_layer[0].onoff_state = VIDEO_ENABLE_STATE_ON_PENDING; |
| } else if (vd_layer[0].onoff_state == |
| VIDEO_ENABLE_STATE_ON_PENDING) { |
| vpp_misc_set |= |
| VPP_VD1_PREBLEND | |
| VPP_VD1_POSTBLEND | |
| VPP_POSTBLEND_EN; |
| vd_layer[0].onoff_state = VIDEO_ENABLE_STATE_IDLE; |
| vd_layer[0].onoff_time = jiffies_to_msecs(jiffies); |
| if (vd_layer[0].global_debug & DEBUG_FLAG_BLACKOUT) |
| pr_info("VIDEO: VsyncEnableVideoLayer\n"); |
| vpu_delay_work_flag |= |
| VPU_VIDEO_LAYER1_CHANGED; |
| force_flush = true; |
| } else if (vd_layer[0].onoff_state == |
| VIDEO_ENABLE_STATE_OFF_REQ) { |
| vpp_misc_set &= ~(VPP_VD1_PREBLEND | |
| VPP_VD1_POSTBLEND); |
| if (mode & COMPOSE_MODE_3D) |
| vpp_misc_set &= ~(VPP_VD2_PREBLEND | |
| VPP_PREBLEND_EN); |
| vd_layer[0].onoff_state = VIDEO_ENABLE_STATE_IDLE; |
| vd_layer[0].onoff_time = jiffies_to_msecs(jiffies); |
| vpu_delay_work_flag |= |
| VPU_VIDEO_LAYER1_CHANGED; |
| if (vd_layer[0].global_debug & DEBUG_FLAG_BLACKOUT) |
| pr_info("VIDEO: VsyncDisableVideoLayer\n"); |
| video1_off_req = 1; |
| force_flush = true; |
| } |
| spin_unlock_irqrestore(&video_onoff_lock, flags); |
| } else if (vd_layer[0].enabled) { |
| vpp_misc_set |= |
| VPP_VD1_PREBLEND | |
| VPP_VD1_POSTBLEND | |
| VPP_POSTBLEND_EN; |
| } |
| |
| if (likely(vd_layer[1].onoff_state != VIDEO_ENABLE_STATE_IDLE)) { |
| /* state change for video layer2 enable/disable */ |
| spin_lock_irqsave(&video2_onoff_lock, flags); |
| if (vd_layer[1].onoff_state == VIDEO_ENABLE_STATE_ON_REQ) { |
| /* |
| * the video layer 2 |
| * is enabled one vsync later, assumming |
| * all registers are ready from RDMA. |
| */ |
| vd_layer[1].onoff_state = VIDEO_ENABLE_STATE_ON_PENDING; |
| } else if (vd_layer[1].onoff_state == |
| VIDEO_ENABLE_STATE_ON_PENDING) { |
| if (mode & COMPOSE_MODE_3D) { |
| vpp_misc_set |= VPP_VD2_PREBLEND | |
| VPP_PREBLEND_EN; |
| vpp_misc_set &= ~VPP_VD2_POSTBLEND; |
| } else if (vd_layer[0].enabled && |
| (mode & COMPOSE_MODE_DV)) { |
| /* DV el case */ |
| vpp_misc_set &= ~(VPP_VD2_PREBLEND | |
| VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); |
| } else if (vd_layer[1].dispbuf) { |
| vpp_misc_set &= |
| ~(VPP_PREBLEND_EN | VPP_VD2_PREBLEND); |
| vpp_misc_set |= VPP_VD2_POSTBLEND | |
| VPP_POSTBLEND_EN; |
| } else { |
| vpp_misc_set |= VPP_VD2_PREBLEND | |
| VPP_PREBLEND_EN; |
| } |
| vpp_misc_set |= (vd_layer[1].layer_alpha |
| << VPP_VD2_ALPHA_BIT); |
| vd_layer[1].onoff_state = VIDEO_ENABLE_STATE_IDLE; |
| vd_layer[1].onoff_time = jiffies_to_msecs(jiffies); |
| vpu_delay_work_flag |= |
| VPU_VIDEO_LAYER2_CHANGED; |
| if (vd_layer[1].global_debug & DEBUG_FLAG_BLACKOUT) |
| pr_info("VIDEO: VsyncEnableVideoLayer2\n"); |
| force_flush = true; |
| } else if (vd_layer[1].onoff_state == |
| VIDEO_ENABLE_STATE_OFF_REQ) { |
| vpp_misc_set &= ~(VPP_VD2_PREBLEND | |
| VPP_VD2_POSTBLEND | VPP_PREBLEND_EN |
| | (0x1ff << VPP_VD2_ALPHA_BIT)); |
| vd_layer[1].onoff_state = VIDEO_ENABLE_STATE_IDLE; |
| vd_layer[1].onoff_time = jiffies_to_msecs(jiffies); |
| vpu_delay_work_flag |= |
| VPU_VIDEO_LAYER2_CHANGED; |
| if (vd_layer[1].global_debug & DEBUG_FLAG_BLACKOUT) |
| pr_info("VIDEO: VsyncDisableVideoLayer2\n"); |
| video2_off_req = 1; |
| force_flush = true; |
| } |
| spin_unlock_irqrestore(&video2_onoff_lock, flags); |
| } else if (vd_layer[1].enabled) { |
| if (mode & COMPOSE_MODE_3D) { |
| vpp_misc_set |= VPP_VD2_PREBLEND | |
| VPP_PREBLEND_EN; |
| vpp_misc_set &= ~VPP_VD2_POSTBLEND; |
| } else if (vd_layer[0].enabled && |
| (mode & COMPOSE_MODE_DV)) { |
| /* DV el case */ |
| vpp_misc_set &= ~(VPP_VD2_PREBLEND | |
| VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); |
| } else if (vd_layer[1].dispbuf) { |
| vpp_misc_set &= |
| ~(VPP_PREBLEND_EN | VPP_VD2_PREBLEND); |
| vpp_misc_set |= VPP_VD2_POSTBLEND | |
| VPP_POSTBLEND_EN; |
| } else { |
| vpp_misc_set |= VPP_VD2_PREBLEND | |
| VPP_PREBLEND_EN; |
| } |
| vpp_misc_set |= (vd_layer[1].layer_alpha |
| << VPP_VD2_ALPHA_BIT); |
| } |
| |
| if (((vd_layer[0].global_output == 0) && !vd_layer[0].force_black) || |
| black_threshold_check(0)) { |
| vd_layer[0].enabled = 0; |
| /* preblend need disable together */ |
| vpp_misc_set &= ~(VPP_VD1_PREBLEND | |
| VPP_VD2_PREBLEND | |
| VPP_VD1_POSTBLEND | |
| VPP_PREBLEND_EN); |
| } else { |
| vd_layer[0].enabled = vd_layer[0].enabled_status_saved; |
| } |
| |
| if (!vd_layer[0].enabled && |
| ((vpp_misc_set & VPP_VD1_POSTBLEND) || |
| (vpp_misc_set & VPP_VD1_PREBLEND))) |
| vpp_misc_set &= ~(VPP_VD1_PREBLEND | |
| VPP_VD1_POSTBLEND | |
| VPP_PREBLEND_EN); |
| |
| if (!(mode & COMPOSE_MODE_3D) && |
| ((vd_layer[1].global_output == 0) || |
| black_threshold_check(1))) { |
| vd_layer[1].enabled = 0; |
| vpp_misc_set &= ~(VPP_VD2_PREBLEND | |
| VPP_VD2_POSTBLEND); |
| } else { |
| vd_layer[1].enabled = vd_layer[1].enabled_status_saved; |
| } |
| |
| if (!vd_layer[0].enabled && is_local_vf(vd_layer[0].dispbuf)) { |
| safe_switch_videolayer(0, false, true); |
| if (vd_layer[0].keep_frame_id == 1) |
| video_pip_keeper_new_frame_notify(); |
| else if (vd_layer[0].keep_frame_id == 0) |
| video_keeper_new_frame_notify(); |
| } |
| |
| if (!vd_layer[1].enabled && is_local_vf(vd_layer[1].dispbuf)) { |
| safe_switch_videolayer(1, false, true); |
| if (vd_layer[1].keep_frame_id == 1) |
| video_pip_keeper_new_frame_notify(); |
| else if (vd_layer[1].keep_frame_id == 0) |
| video_keeper_new_frame_notify(); |
| } |
| |
| if (!vd_layer[1].enabled && |
| ((vpp_misc_set & VPP_VD2_POSTBLEND) || |
| (vpp_misc_set & VPP_VD2_PREBLEND))) |
| vpp_misc_set &= ~(VPP_VD2_PREBLEND | |
| VPP_VD2_POSTBLEND); |
| |
| force_flush |= vpp_zorder_check(); |
| |
| if (!legacy_vpp) { |
| u32 set_value = 0; |
| |
| /* for sr core0, put it between prebld & pps as default */ |
| if (vd1_frame_par && |
| (vd1_frame_par->sr_core_support & SUPER_CORE0_SUPPORT)) |
| if (vd1_frame_par->sr0_position) |
| vpp_misc_set |= |
| PREBLD_SR0_VD1_SCALER; |
| else /* SR0_AFTER_DNLP */ |
| vpp_misc_set &= |
| ~PREBLD_SR0_VD1_SCALER; |
| else |
| vpp_misc_set |= |
| PREBLD_SR0_VD1_SCALER; |
| /* for sr core1, put it before post blend as default */ |
| if (vd1_frame_par && |
| (vd1_frame_par->sr_core_support & SUPER_CORE1_SUPPORT)) |
| if (vd1_frame_par->sr1_position) |
| vpp_misc_set |= |
| DNLP_SR1_CM; |
| else /* SR1_AFTER_POSTBLEN */ |
| vpp_misc_set &= |
| ~DNLP_SR1_CM; |
| else |
| vpp_misc_set |= |
| DNLP_SR1_CM; |
| |
| vpp_misc_set &= |
| ((1 << 29) | VPP_CM_ENABLE | |
| (0x1ff << VPP_VD2_ALPHA_BIT) | |
| VPP_VD2_PREBLEND | |
| VPP_VD1_PREBLEND | |
| VPP_VD2_POSTBLEND | |
| VPP_VD1_POSTBLEND | |
| VPP_PREBLEND_EN | |
| VPP_POSTBLEND_EN | |
| 0xf); |
| |
| /* if vd2 is bottom layer, need remove alpha for vd2 */ |
| /* 3d case vd2 preblend, need remove alpha for vd2 */ |
| if ((((vpp_misc_set & VPP_VD1_POSTBLEND) == 0) && |
| (vpp_misc_set & VPP_VD2_POSTBLEND)) || |
| (vpp_misc_set & VPP_VD2_PREBLEND)) { |
| vpp_misc_set &= ~(0x1ff << VPP_VD2_ALPHA_BIT); |
| vpp_misc_set |= (vd_layer[1].layer_alpha |
| << VPP_VD2_ALPHA_BIT); |
| } |
| |
| vpp_misc_save &= |
| ((1 << 29) | VPP_CM_ENABLE | |
| (0x1ff << VPP_VD2_ALPHA_BIT) | |
| VPP_VD2_PREBLEND | |
| VPP_VD1_PREBLEND | |
| VPP_VD2_POSTBLEND | |
| VPP_VD1_POSTBLEND | |
| VPP_PREBLEND_EN | |
| VPP_POSTBLEND_EN | |
| 0xf); |
| if ((vpp_misc_set != vpp_misc_save) || force_flush) { |
| u32 port_val[3] = {0, 0, 0}; |
| u32 vd1_port, vd2_port, icnt; |
| u32 post_blend_reg[3] = { |
| VD1_BLEND_SRC_CTRL, |
| VD2_BLEND_SRC_CTRL, |
| OSD2_BLEND_SRC_CTRL |
| }; |
| |
| /* just reset the select port */ |
| if ((glayer_info[0].cur_sel_port > 2) || |
| (glayer_info[1].cur_sel_port > 2)) { |
| glayer_info[0].cur_sel_port = 0; |
| glayer_info[1].cur_sel_port = 1; |
| } |
| |
| vd1_port = glayer_info[0].cur_sel_port; |
| vd2_port = glayer_info[1].cur_sel_port; |
| |
| /* post bld premult*/ |
| port_val[0] |= (1 << 16); |
| |
| /* vd2 path sel */ |
| if (vpp_misc_set & VPP_VD2_POSTBLEND) |
| port_val[1] |= (1 << 20); |
| else |
| port_val[1] &= ~(1 << 20); |
| |
| /* osd2 path sel */ |
| port_val[2] |= (1 << 20); |
| |
| if (vpp_misc_set & VPP_VD1_POSTBLEND) { |
| /* post src */ |
| port_val[vd1_port] |= (1 << 8); |
| port_val[0] |= |
| ((1 << 4) | /* pre bld premult*/ |
| (1 << 0)); /* pre bld src 1 */ |
| } else { |
| port_val[0] &= ~0xff; |
| } |
| |
| if (vpp_misc_set & VPP_VD2_POSTBLEND) |
| /* post src */ |
| port_val[vd2_port] |= (2 << 8); |
| else if (vpp_misc_set & VPP_VD2_PREBLEND) |
| port_val[1] |= |
| ((1 << 4) | /* pre bld premult*/ |
| (2 << 0)); /* pre bld src 1 */ |
| |
| for (icnt = 0; icnt < 3; icnt++) |
| VSYNC_WR_MPEG_REG( |
| post_blend_reg[icnt] |
| + vpp_off, |
| port_val[icnt]); |
| |
| set_value = vpp_misc_set; |
| set_value &= |
| ((1 << 29) | VPP_CM_ENABLE | |
| (0x1ff << VPP_VD2_ALPHA_BIT) | |
| VPP_VD2_PREBLEND | |
| VPP_VD1_PREBLEND | |
| VPP_VD2_POSTBLEND | |
| VPP_VD1_POSTBLEND | |
| 0xf); |
| if ((vpp_misc_set & VPP_VD2_PREBLEND) && |
| (vpp_misc_set & VPP_VD1_PREBLEND)) |
| set_value |= VPP_PREBLEND_EN; |
| if (mode & COMPOSE_MODE_BYPASS_CM) |
| set_value &= ~VPP_CM_ENABLE; |
| set_value |= VPP_POSTBLEND_EN; |
| set_value |= VPP_PREBLEND_EN; |
| if (osd_preblend_en) { |
| set_value |= VPP_VD1_POSTBLEND; |
| set_value |= VPP_VD1_PREBLEND; |
| } |
| VSYNC_WR_MPEG_REG( |
| VPP_MISC + vpp_off, |
| set_value); |
| } |
| } else if (vpp_misc_save != vpp_misc_set) { |
| VSYNC_WR_MPEG_REG( |
| VPP_MISC + vpp_off, |
| vpp_misc_set); |
| } |
| |
| post_blend_dummy_data_update(); |
| |
| if ((vd_layer[1].dispbuf && video2_off_req) || |
| (!vd_layer[1].dispbuf && |
| (video1_off_req || video2_off_req))) |
| disable_vd2_blend(&vd_layer[1]); |
| |
| if (video1_off_req) |
| disable_vd1_blend(&vd_layer[0]); |
| } |
| |
| /********************************************************* |
| * frame canvas APIs |
| *********************************************************/ |
| static void vframe_canvas_set( |
| struct canvas_config_s *config, |
| u32 planes, |
| u32 *index) |
| { |
| int i; |
| u32 *canvas_index = index; |
| |
| struct canvas_config_s *cfg = config; |
| |
| for (i = 0; i < planes; i++, canvas_index++, cfg++) |
| canvas_config_config(*canvas_index, cfg); |
| } |
| |
| static bool is_vframe_changed( |
| u8 layer_id, |
| struct vframe_s *cur_vf, |
| struct vframe_s *new_vf) |
| { |
| if (cur_vf && new_vf && |
| (cur_vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) && |
| (cur_vf->ratio_control == new_vf->ratio_control) && |
| memcmp(&cur_vf->pic_mode, &new_vf->pic_mode, |
| sizeof(struct vframe_pic_mode_s))) |
| return true; |
| else if (cur_vf && |
| memcmp(&cur_vf->pic_mode, &gpic_info[layer_id], |
| sizeof(struct vframe_pic_mode_s))) |
| return true; |
| |
| if ((glayer_info[layer_id].reverse != reverse) || |
| (glayer_info[layer_id].proc_3d_type != process_3d_type)) |
| return true; |
| |
| if (cur_vf && new_vf && |
| (((cur_vf->type & VIDTYPE_COMPRESS) && |
| ((cur_vf->compWidth != new_vf->compWidth) || |
| (cur_vf->compHeight != new_vf->compHeight))) || |
| (cur_vf->bufWidth != new_vf->bufWidth) || |
| (cur_vf->width != new_vf->width) || |
| (cur_vf->height != new_vf->height) || |
| (cur_vf->sar_width != new_vf->sar_width) || |
| (cur_vf->sar_height != new_vf->sar_height) || |
| (cur_vf->bitdepth != new_vf->bitdepth) || |
| (cur_vf->trans_fmt != new_vf->trans_fmt) || |
| (cur_vf->ratio_control != new_vf->ratio_control) || |
| ((cur_vf->type_backup & VIDTYPE_INTERLACE) != |
| (new_vf->type_backup & VIDTYPE_INTERLACE)) || |
| (cur_vf->type != new_vf->type))) |
| return true; |
| return false; |
| } |
| |
| int get_layer_display_canvas(u8 layer_id) |
| { |
| int ret = -1; |
| struct video_layer_s *layer = NULL; |
| |
| if (layer_id >= MAX_VD_LAYER) |
| return -1; |
| |
| layer = &vd_layer[layer_id]; |
| ret = READ_VCBUS_REG(layer->vd_mif_reg.vd_if0_canvas0); |
| return ret; |
| } |
| |
| int set_layer_display_canvas( |
| u8 layer_id, struct vframe_s *vf, |
| struct vpp_frame_par_s *cur_frame_par, |
| struct disp_info_s *disp_info) |
| { |
| u32 *cur_canvas_tbl; |
| u8 cur_canvas_id; |
| struct video_layer_s *layer = NULL; |
| bool is_mvc = false; |
| bool update_mif = true; |
| |
| if (layer_id >= MAX_VD_LAYER) |
| return -1; |
| |
| if ((vf->type & VIDTYPE_MVC) && (layer_id == 0)) |
| is_mvc = true; |
| |
| layer = &vd_layer[layer_id]; |
| |
| cur_canvas_id = layer->cur_canvas_id; |
| cur_canvas_tbl = |
| &layer->canvas_tbl[cur_canvas_id][0]; |
| |
| /* switch buffer */ |
| if (!glayer_info[layer_id].need_no_compress && |
| (vf->type & VIDTYPE_COMPRESS)) { |
| VSYNC_WR_MPEG_REG( |
| layer->vd_afbc_reg.afbc_head_baddr, |
| vf->compHeadAddr >> 4); |
| VSYNC_WR_MPEG_REG( |
| layer->vd_afbc_reg.afbc_body_baddr, |
| vf->compBodyAddr >> 4); |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if ((layer_id == 0) && |
| is_di_post_mode(vf) && |
| is_di_post_link_on()) |
| update_mif = false; |
| #endif |
| if (vf->canvas0Addr == 0) |
| update_mif = false; |
| |
| if (update_mif) { |
| if (vf->canvas0Addr != (u32)-1) { |
| canvas_copy( |
| vf->canvas0Addr & 0xff, |
| cur_canvas_tbl[0]); |
| canvas_copy( |
| (vf->canvas0Addr >> 8) & 0xff, |
| cur_canvas_tbl[1]); |
| canvas_copy( |
| (vf->canvas0Addr >> 16) & 0xff, |
| cur_canvas_tbl[2]); |
| } else { |
| vframe_canvas_set( |
| &vf->canvas0_config[0], |
| vf->plane_num, |
| &cur_canvas_tbl[0]); |
| } |
| if ((layer_id == 0) && |
| (is_mvc || process_3d_type)) { |
| if (vf->canvas1Addr != (u32)-1) { |
| canvas_copy( |
| vf->canvas1Addr & 0xff, |
| cur_canvas_tbl[3]); |
| canvas_copy( |
| (vf->canvas1Addr >> 8) & 0xff, |
| cur_canvas_tbl[4]); |
| canvas_copy( |
| (vf->canvas1Addr >> 16) & 0xff, |
| cur_canvas_tbl[5]); |
| } else { |
| vframe_canvas_set( |
| &vf->canvas1_config[0], |
| vf->plane_num, |
| &cur_canvas_tbl[3]); |
| } |
| } |
| VSYNC_WR_MPEG_REG( |
| layer->vd_mif_reg.vd_if0_canvas0, |
| layer->disp_canvas[cur_canvas_id][0]); |
| |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG( |
| vd_layer[1].vd_mif_reg.vd_if0_canvas0, |
| layer->disp_canvas[cur_canvas_id][1]); |
| if (cur_frame_par && |
| (cur_frame_par->vpp_2pic_mode == 1)) { |
| VSYNC_WR_MPEG_REG( |
| layer->vd_mif_reg.vd_if0_canvas1, |
| layer->disp_canvas[cur_canvas_id][0]); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG( |
| vd_layer[1].vd_mif_reg.vd_if0_canvas1, |
| layer->disp_canvas[cur_canvas_id][0]); |
| } else { |
| VSYNC_WR_MPEG_REG( |
| layer->vd_mif_reg.vd_if0_canvas1, |
| layer->disp_canvas[cur_canvas_id][1]); |
| if (is_mvc) |
| VSYNC_WR_MPEG_REG( |
| vd_layer[1].vd_mif_reg.vd_if0_canvas1, |
| layer->disp_canvas[cur_canvas_id][0]); |
| } |
| if (cur_frame_par && disp_info && |
| (disp_info->proc_3d_type & MODE_3D_ENABLE) && |
| (disp_info->proc_3d_type & MODE_3D_TO_2D_R) && |
| (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1)) { |
| VSYNC_WR_MPEG_REG( |
| layer->vd_mif_reg.vd_if0_canvas0, |
| layer->disp_canvas[cur_canvas_id][1]); |
| VSYNC_WR_MPEG_REG( |
| layer->vd_mif_reg.vd_if0_canvas1, |
| layer->disp_canvas[cur_canvas_id][1]); |
| if (is_mvc) { |
| VSYNC_WR_MPEG_REG( |
| vd_layer[1].vd_mif_reg.vd_if0_canvas0, |
| layer->disp_canvas[cur_canvas_id][1]); |
| VSYNC_WR_MPEG_REG( |
| vd_layer[1].vd_mif_reg.vd_if0_canvas1, |
| layer->disp_canvas[cur_canvas_id][1]); |
| } |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| layer->next_canvas_id = layer->cur_canvas_id ? 0 : 1; |
| #endif |
| } |
| return 0; |
| } |
| |
| u32 *get_canvase_tbl(u8 layer_id) |
| { |
| struct video_layer_s *layer = NULL; |
| |
| if (layer_id >= MAX_VD_LAYER) |
| return NULL; |
| |
| layer = &vd_layer[layer_id]; |
| return (u32 *)&layer->canvas_tbl[0][0]; |
| } |
| |
| s32 layer_swap_frame( |
| struct vframe_s *vf, u8 layer_id, |
| bool force_toggle, |
| const struct vinfo_s *vinfo) |
| { |
| bool first_picture = false; |
| bool enable_layer = false; |
| bool frame_changed; |
| struct video_layer_s *layer = NULL; |
| struct disp_info_s *layer_info = NULL; |
| int ret = vppfilter_success; |
| bool is_mvc = false; |
| bool bypass_sr = false; |
| |
| if (!vf) |
| return vppfilter_fail; |
| |
| layer = &vd_layer[layer_id]; |
| layer_info = &glayer_info[layer_id]; |
| |
| if ((vf->type & VIDTYPE_MVC) && (layer_id == 0)) |
| is_mvc = true; |
| |
| if (layer->dispbuf != vf) { |
| layer->new_vframe_count++; |
| layer->new_frame = true; |
| if (!layer->dispbuf || |
| (layer->new_vframe_count == 1) || |
| (is_local_vf(layer->dispbuf))) |
| first_picture = true; |
| } |
| |
| if (layer->property_changed) { |
| layer->force_config_cnt = 2; |
| layer->property_changed = false; |
| force_toggle = true; |
| } |
| if (layer->force_config_cnt > 0) { |
| layer->force_config_cnt--; |
| force_toggle = true; |
| } |
| |
| if ((layer->global_debug & DEBUG_FLAG_BLACKOUT) && first_picture) |
| pr_info("first swap picture {%d,%d} pts:%x,\n", |
| vf->width, vf->height, vf->pts); |
| |
| set_layer_display_canvas( |
| layer->layer_id, |
| vf, layer->cur_frame_par, layer_info); |
| |
| frame_changed = is_vframe_changed( |
| layer->layer_id, |
| layer->dispbuf, vf); |
| |
| /* enable new config on the new frames */ |
| if (first_picture || force_toggle || frame_changed) { |
| if (layer->next_frame_par == layer->cur_frame_par) |
| layer->next_frame_par = |
| (&layer->frame_parms[0] == |
| layer->next_frame_par) ? |
| &layer->frame_parms[1] : |
| &layer->frame_parms[0]; |
| |
| /* FIXME: remove the global variables */ |
| glayer_info[layer->layer_id].reverse = reverse; |
| glayer_info[layer->layer_id].mirror = mirror; |
| glayer_info[layer->layer_id].proc_3d_type = |
| process_3d_type; |
| |
| if (is_dolby_vision_on() && |
| is_dolby_vision_stb_mode() && |
| for_dolby_vision_certification()) |
| bypass_sr = true; |
| else if ((vf->width >= disable_sr_threshold) || |
| ((vf->type & VIDTYPE_COMPRESS) && |
| (vf->compWidth >= disable_sr_threshold))) |
| bypass_sr = true; |
| |
| ret = vpp_set_filters( |
| &glayer_info[layer->layer_id], vf, |
| layer->next_frame_par, vinfo, bypass_sr, 1); |
| |
| memcpy(&gpic_info[layer->layer_id], &vf->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| |
| if ((ret == vppfilter_success_and_changed) || |
| (ret == vppfilter_changed_but_hold)) |
| layer->property_changed = true; |
| |
| if (ret != vppfilter_changed_but_hold) |
| layer->new_vpp_setting = true; |
| |
| if (layer->layer_id == 0) { |
| if (((vf->width > 1920) && (vf->height > 1088)) || |
| ((vf->type & VIDTYPE_COMPRESS) && |
| (vf->compWidth > 1920) && |
| (vf->compHeight > 1080))) { |
| VPU_VD1_CLK_SWITCH(1); |
| } else { |
| VPU_VD1_CLK_SWITCH(0); |
| } |
| } else { |
| if (((vf->width > 1920) && (vf->height > 1088)) || |
| ((vf->type & VIDTYPE_COMPRESS) && |
| (vf->compWidth > 1920) && |
| (vf->compHeight > 1080))) { |
| VPU_VD2_CLK_SWITCH(1); |
| } else { |
| VPU_VD2_CLK_SWITCH(0); |
| } |
| } |
| } |
| |
| if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && |
| (!layer->force_config_cnt || (vf != layer->dispbuf))) { |
| if (layer->disable_video == VIDEO_DISABLE_FORNEXT) { |
| enable_layer = true; |
| layer->disable_video = VIDEO_DISABLE_NONE; |
| } |
| if (first_picture && |
| (layer->disable_video != |
| VIDEO_DISABLE_NORMAL)) |
| enable_layer = true; |
| if (enable_layer) { |
| if (layer->layer_id == 0) |
| enable_video_layer(); |
| if ((layer->layer_id == 1) || is_mvc) |
| enable_video_layer2(); |
| } |
| } |
| |
| if (first_picture) |
| layer->new_vpp_setting = true; |
| layer->dispbuf = vf; |
| return ret; |
| } |
| |
| /* pip apha APIs */ |
| static void vd1_set_alpha(u32 win_en, struct pip_alpha_scpxn_s *alpha_win) |
| { |
| int i; |
| u32 alph_gen_mode = 1; |
| /* 0:original, 1: 0.5 alpha 2: 0.25/0.5/0.75 */ |
| u32 alph_gen_byps = 0; |
| |
| if (!win_en) |
| alph_gen_byps = 1; |
| VSYNC_WR_MPEG_REG(VD1_PIP_ALPH_CTRL, |
| ((0 & 0x1) << 28) | |
| ((win_en & 0xffff) << 12) | |
| ((0 & 0x1ff) << 3) | |
| ((alph_gen_mode & 0x3) << 1) | |
| ((alph_gen_byps & 0x1) << 0)); |
| for (i = 0; i < MAX_PIP_WINDOW; i++) { |
| VSYNC_WR_MPEG_REG(VD1_PIP_ALPH_SCP_H_0 + i, |
| (alpha_win->scpxn_end_h[i] & 0x1fff) << 16 | |
| (alpha_win->scpxn_bgn_h[i] & 0x1fff)); |
| |
| VSYNC_WR_MPEG_REG(VD1_PIP_ALPH_SCP_V_0 + i, |
| (alpha_win->scpxn_end_v[i] & 0x1fff) << 16 | |
| (alpha_win->scpxn_bgn_v[i] & 0x1fff)); |
| } |
| } |
| |
| static void vd2_set_alpha(u32 win_en, struct pip_alpha_scpxn_s *alpha_win) |
| { |
| int i; |
| u32 alph_gen_mode = 1; |
| /* 0:original, 1: 0.5 alpha 2: 0.25/0.5/0.75 */ |
| u32 alph_gen_byps = 0; |
| |
| if (!win_en) |
| alph_gen_byps = 1; |
| VSYNC_WR_MPEG_REG(VD2_PIP_ALPH_CTRL, |
| ((0 & 0x1) << 28) | |
| ((win_en & 0xffff) << 12) | |
| ((0 & 0x1ff) << 3) | |
| ((alph_gen_mode & 0x3) << 1) | |
| ((alph_gen_byps & 0x1) << 0)); |
| |
| for (i = 0; i < MAX_PIP_WINDOW; i++) { |
| VSYNC_WR_MPEG_REG(VD2_PIP_ALPH_SCP_H_0 + i, |
| (alpha_win->scpxn_end_h[i] & 0x1fff) << 16 | |
| (alpha_win->scpxn_bgn_h[i] & 0x1fff)); |
| |
| VSYNC_WR_MPEG_REG(VD2_PIP_ALPH_SCP_V_0 + i, |
| (alpha_win->scpxn_end_v[i] & 0x1fff) << 16 | |
| (alpha_win->scpxn_bgn_v[i] & 0x1fff)); |
| } |
| } |
| |
| void set_alpha(u8 layer_id, |
| u32 win_en, |
| struct pip_alpha_scpxn_s *alpha_win) |
| { |
| if (glayer_info[layer_id].alpha_support) { |
| if (layer_id == 0) |
| vd1_set_alpha(win_en, alpha_win); |
| else if (layer_id == 1) |
| vd2_set_alpha(win_en, alpha_win); |
| } |
| } |
| |
| /********************************************************* |
| * vout APIs |
| *********************************************************/ |
| int detect_vout_type(const struct vinfo_s *vinfo) |
| { |
| int vout_type = VOUT_TYPE_PROG; |
| |
| if (vinfo && (vinfo->field_height != vinfo->height)) { |
| if ((vinfo->height == 576) || (vinfo->height == 480)) |
| vout_type = (READ_VCBUS_REG(ENCI_INFO_READ) & |
| (1 << 29)) ? |
| VOUT_TYPE_BOT_FIELD : VOUT_TYPE_TOP_FIELD; |
| else if (vinfo->height == 1080) |
| vout_type = (((READ_VCBUS_REG(ENCP_INFO_READ) >> 16) & |
| 0x1fff) < 562) ? |
| VOUT_TYPE_TOP_FIELD : VOUT_TYPE_BOT_FIELD; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| if (is_vsync_rdma_enable()) { |
| if (vout_type == VOUT_TYPE_TOP_FIELD) |
| vout_type = VOUT_TYPE_BOT_FIELD; |
| else if (vout_type == VOUT_TYPE_BOT_FIELD) |
| vout_type = VOUT_TYPE_TOP_FIELD; |
| } |
| #endif |
| } |
| return vout_type; |
| } |
| |
| int calc_hold_line(void) |
| { |
| if ((READ_VCBUS_REG(ENCI_VIDEO_EN) & 1) == 0) |
| return READ_VCBUS_REG(ENCP_VIDEO_VAVON_BLINE) >> 1; |
| else |
| return READ_VCBUS_REG(ENCP_VFIFO2VD_LINE_TOP_START) >> 1; |
| } |
| |
| u32 get_active_start_line(void) |
| { |
| u32 active_line_begin = 0; |
| |
| switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) { |
| case 0: |
| active_line_begin = |
| READ_VCBUS_REG(ENCL_VIDEO_VAVON_BLINE); |
| break; |
| case 1: |
| active_line_begin = |
| READ_VCBUS_REG(ENCI_VFIFO2VD_LINE_TOP_START); |
| break; |
| case 2: |
| active_line_begin = |
| READ_VCBUS_REG(ENCP_VIDEO_VAVON_BLINE); |
| break; |
| case 3: |
| active_line_begin = |
| READ_VCBUS_REG(ENCT_VIDEO_VAVON_BLINE); |
| break; |
| } |
| |
| return active_line_begin; |
| } |
| |
| u32 get_cur_enc_line(void) |
| { |
| u32 ret = 0; |
| |
| switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) { |
| case 0: |
| ret = (READ_VCBUS_REG(ENCL_INFO_READ) >> 16) & 0x1fff; |
| break; |
| case 1: |
| ret = (READ_VCBUS_REG(ENCI_INFO_READ) >> 16) & 0x1fff; |
| break; |
| case 2: |
| ret = (READ_VCBUS_REG(ENCP_INFO_READ) >> 16) & 0x1fff; |
| break; |
| case 3: |
| ret = (READ_VCBUS_REG(ENCT_INFO_READ) >> 16) & 0x1fff; |
| break; |
| } |
| return ret; |
| } |
| |
| static void do_vpu_delay_work(struct work_struct *work) |
| { |
| unsigned long flags; |
| unsigned int r; |
| |
| if (vpu_delay_work_flag & VPU_VIDEO_LAYER1_CHANGED) |
| vpu_delay_work_flag &= ~VPU_VIDEO_LAYER1_CHANGED; |
| |
| if (vpu_delay_work_flag & VPU_VIDEO_LAYER2_CHANGED) |
| vpu_delay_work_flag &= ~VPU_VIDEO_LAYER2_CHANGED; |
| |
| spin_lock_irqsave(&delay_work_lock, flags); |
| |
| if (vpu_delay_work_flag & VPU_DELAYWORK_VPU_VD1_CLK) { |
| vpu_delay_work_flag &= ~VPU_DELAYWORK_VPU_VD1_CLK; |
| |
| spin_unlock_irqrestore(&delay_work_lock, flags); |
| |
| if (vpu_vd1_clk_level > 0) |
| request_vpu_clk_vmod(360000000, VPU_VIU_VD1); |
| else |
| release_vpu_clk_vmod(VPU_VIU_VD1); |
| |
| spin_lock_irqsave(&delay_work_lock, flags); |
| } |
| |
| if (vpu_delay_work_flag & VPU_DELAYWORK_VPU_VD2_CLK) { |
| vpu_delay_work_flag &= ~VPU_DELAYWORK_VPU_VD2_CLK; |
| |
| /* FIXME: check the right vd2 clock */ |
| #ifdef CHECK_LATER |
| spin_unlock_irqrestore(&delay_work_lock, flags); |
| |
| if (vpu_vd2_clk_level > 0) |
| request_vpu_clk_vmod(360000000, VPU_VIU_VD2); |
| else |
| release_vpu_clk_vmod(VPU_VIU_VD2); |
| |
| spin_lock_irqsave(&delay_work_lock, flags); |
| #endif |
| } |
| |
| r = READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off); |
| |
| if (vpu_mem_power_off_count > 0) { |
| vpu_mem_power_off_count--; |
| |
| if (vpu_mem_power_off_count == 0) { |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_VD1) && |
| ((r & VPP_VD1_PREBLEND) == 0)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_VD1; |
| |
| switch_vpu_mem_pd_vmod( |
| VPU_VIU_VD1, |
| VPU_MEM_POWER_DOWN); |
| switch_vpu_mem_pd_vmod( |
| VPU_AFBC_DEC, |
| VPU_MEM_POWER_DOWN); |
| #ifdef DI_POST_PWR |
| switch_vpu_mem_pd_vmod( |
| VPU_DI_POST, |
| VPU_MEM_POWER_DOWN); |
| #endif |
| if (!legacy_vpp) |
| switch_vpu_mem_pd_vmod( |
| VPU_VD1_SCALE, |
| VPU_MEM_POWER_DOWN); |
| if (glayer_info[0].fgrain_support) |
| switch_vpu_mem_pd_vmod( |
| VPU_FGRAIN0, |
| VPU_MEM_POWER_DOWN); |
| } |
| |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_VD2) && |
| ((r & VPP_VD2_PREBLEND) == 0)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_VD2; |
| |
| switch_vpu_mem_pd_vmod( |
| VPU_VIU_VD2, |
| VPU_MEM_POWER_DOWN); |
| switch_vpu_mem_pd_vmod( |
| VPU_AFBC_DEC1, |
| VPU_MEM_POWER_DOWN); |
| if (!legacy_vpp) |
| switch_vpu_mem_pd_vmod( |
| VPU_VD2_SCALE, |
| VPU_MEM_POWER_DOWN); |
| if (glayer_info[1].fgrain_support) |
| switch_vpu_mem_pd_vmod( |
| VPU_FGRAIN1, |
| VPU_MEM_POWER_DOWN); |
| } |
| } |
| } |
| if (dv_mem_power_off_count > 0) { |
| dv_mem_power_off_count--; |
| if (dv_mem_power_off_count == 0) { |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_DOLBY0)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_DOLBY0; |
| switch_vpu_mem_pd_vmod( |
| VPU_DOLBY0, |
| VPU_MEM_POWER_DOWN); |
| } |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1A)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1A; |
| switch_vpu_mem_pd_vmod( |
| VPU_DOLBY1A, |
| VPU_MEM_POWER_DOWN); |
| } |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1B)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_DOLBY1B; |
| switch_vpu_mem_pd_vmod( |
| VPU_DOLBY1B, |
| VPU_MEM_POWER_DOWN); |
| } |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_DOLBY2)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_DOLBY2; |
| switch_vpu_mem_pd_vmod( |
| VPU_DOLBY2, |
| VPU_MEM_POWER_DOWN); |
| } |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_DOLBY_CORE3)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_DOLBY_CORE3; |
| switch_vpu_mem_pd_vmod( |
| VPU_DOLBY_CORE3, |
| VPU_MEM_POWER_DOWN); |
| } |
| if ((vpu_delay_work_flag & |
| VPU_DELAYWORK_MEM_POWER_OFF_PRIME_DOLBY)) { |
| vpu_delay_work_flag &= |
| ~VPU_DELAYWORK_MEM_POWER_OFF_PRIME_DOLBY; |
| switch_vpu_mem_pd_vmod( |
| VPU_PRIME_DOLBY_RAM, |
| VPU_MEM_POWER_DOWN); |
| } |
| } |
| } |
| spin_unlock_irqrestore(&delay_work_lock, flags); |
| } |
| |
| void vpu_work_process(void) |
| { |
| if (vpu_delay_work_flag) |
| schedule_work(&vpu_delay_work); |
| } |
| |
| int vpp_crc_check(u32 vpp_crc_en) |
| { |
| u32 val = 0; |
| int vpp_crc_result = 0; |
| static u32 val_pre, crc_cnt; |
| |
| if (vpp_crc_en && cpu_after_eq(MESON_CPU_MAJOR_ID_SM1)) { |
| VSYNC_WR_MPEG_REG(VPP_CRC_CHK, 1); |
| if (crc_cnt >= 1) { |
| val = VSYNC_RD_MPEG_REG(VPP_RO_CRCSUM); |
| if (val_pre && (val != val_pre)) |
| vpp_crc_result = -1; |
| else |
| vpp_crc_result = val; |
| } |
| val_pre = val; |
| crc_cnt++; |
| } else { |
| crc_cnt = 0; |
| } |
| return vpp_crc_result; |
| } |
| |
| int vpp_crc_viu2_check(u32 vpp_crc_en) |
| { |
| int vpp_crc_result = 0; |
| |
| if (vpp_crc_en) |
| vpp_crc_result = READ_VCBUS_REG(VPP2_RO_CRCSUM); |
| |
| return vpp_crc_result; |
| } |
| |
| void enable_vpp_crc_viu2(u32 vpp_crc_en) |
| { |
| if (vpp_crc_en) |
| WRITE_VCBUS_REG_BITS(VPP2_CRC_CHK, 1, 0, 1); |
| } |
| |
| int get_osd_reverse(void) |
| { |
| return (VSYNC_RD_MPEG_REG(VIU_OSD1_BLK0_CFG_W0) >> 28) & 3; |
| } |
| EXPORT_SYMBOL(get_osd_reverse); |
| |
| void dump_pps_coefs_info(u8 layer_id, u8 bit9_mode, u8 coef_type) |
| { |
| u32 pps_coef_idx_save; |
| int i; |
| |
| /* bit9_mode : 0 8bit, 1: 9bit*/ |
| /* coef_type : 0 horz, 1: vert*/ |
| if (layer_id == 0) { |
| pps_coef_idx_save = READ_VCBUS_REG(VPP_SCALE_COEF_IDX); |
| if (hscaler_8tap_enable[layer_id]) { |
| if (bit9_mode) { |
| if (coef_type == 0) { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004100 | |
| VPP_COEF_9BIT); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 8TAP 9bit HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 8TAP 9bit HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004180 | |
| VPP_COEF_9BIT); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 8TAP 9bit HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 8TAP 9bit HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } else { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004000 | |
| VPP_COEF_9BIT); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 9bit VERT coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 9bit VERT coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } |
| |
| } else { |
| if (coef_type == 0) { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004100); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 8TAP HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004180); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 8 TAP HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } else { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004000); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 VERT coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } |
| } |
| } else { |
| if (bit9_mode) { |
| if (coef_type == 0) { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004100 | |
| VPP_COEF_9BIT); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 9bit HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 9bit HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } else { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004000 | |
| VPP_COEF_9BIT); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 9bit VERT coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 9bit VERT coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } |
| } else { |
| if (coef_type == 0) { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004100); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 HORZ coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } else { |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, |
| 0x00004000); |
| READ_VCBUS_REG(VPP_SCALE_COEF); |
| for (i = 0; |
| i < VPP_FILER_COEFS_NUM; i++) |
| pr_info("VD1 VERT coef[%d]=%x\n", |
| i, |
| READ_VCBUS_REG(VPP_SCALE_COEF)); |
| } |
| } |
| } |
| WRITE_VCBUS_REG(VPP_SCALE_COEF_IDX, pps_coef_idx_save); |
| } else if (layer_id == 1) { |
| pps_coef_idx_save = READ_VCBUS_REG(VD2_SCALE_COEF_IDX); |
| if (hscaler_8tap_enable[layer_id]) { |
| WRITE_VCBUS_REG(VD2_SCALE_COEF_IDX, 0x00004100); |
| for (i = 0; i < 34; i++) |
| pr_info("VD2 8TAP HORZ coef[%d]=%x\n", |
| i, READ_VCBUS_REG(VD2_SCALE_COEF)); |
| WRITE_VCBUS_REG(VD2_SCALE_COEF_IDX, 0x00004180); |
| for (i = 0; i < 34; i++) |
| pr_info("VD2 8TAP HORZ coef[%d]=%x\n", |
| i, READ_VCBUS_REG(VD2_SCALE_COEF)); |
| WRITE_VCBUS_REG(VD2_SCALE_COEF_IDX, 0x00004000); |
| for (i = 0; i < 34; i++) |
| pr_info("VD2 VERT coef[%d]=%x\n", |
| i, READ_VCBUS_REG(VD2_SCALE_COEF)); |
| } else { |
| WRITE_VCBUS_REG(VD2_SCALE_COEF_IDX, 0x00004100); |
| for (i = 0; i < 34; i++) |
| pr_info("VD2 HORZ coef[%d]=%x\n", |
| i, READ_VCBUS_REG(VD2_SCALE_COEF)); |
| WRITE_VCBUS_REG(VD2_SCALE_COEF_IDX, 0x00004000); |
| for (i = 0; i < 34; i++) |
| pr_info("VD2 VERT coef[%d]=%x\n", |
| i, READ_VCBUS_REG(VD2_SCALE_COEF)); |
| } |
| WRITE_VCBUS_REG(VD2_SCALE_COEF_IDX, pps_coef_idx_save); |
| } |
| } |
| |
| /********************************************************* |
| * Film Grain APIs |
| *********************************************************/ |
| #define FGRAIN_TBL_SIZE (498 * 16) |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_LUT_DMA |
| static void fgrain_set_config(struct fgrain_setting_s *setting) |
| { |
| u32 reg_fgrain_glb_en = 1 << 0; |
| u32 reg_fgrain_loc_en = 1 << 1; |
| u32 reg_block_mode = 1 << 2; |
| u32 reg_rev_mode = 0 << 4; |
| u32 reg_comp_bits = 0 << 6; |
| /* unsigned , RW, default = 0:8bits; 1:10bits, else 12 bits */ |
| u32 reg_fmt_mode = 2 << 8; |
| /* unsigned , RW, default = 0:444; 1:422; 2:420; 3:reserved */ |
| u32 reg_last_in_mode = 0; |
| /* for none-afbc, it need set to 1, default it is 0 */ |
| u32 reg_fgrain_ext_imode = 1; |
| /* unsigned , RW, default = 0 to indicate the |
| *input data is *4 in 8bit mode |
| */ |
| u32 layer_id = 0; |
| struct hw_fg_reg_s *fg_reg; |
| |
| if (!glayer_info[layer_id].fgrain_support) |
| return; |
| if (!setting) |
| return; |
| layer_id = setting->id; |
| fg_reg = &vd_layer[layer_id].fg_reg; |
| |
| reg_block_mode = setting->afbc << 2; |
| reg_rev_mode = setting->reverse << 4; |
| reg_comp_bits = setting->bitdepth << 6; |
| reg_fmt_mode = setting->fmt_mode << 8; |
| reg_last_in_mode = setting->last_in_mode; |
| |
| VSYNC_WR_MPEG_REG_BITS(fg_reg->fgrain_ctrl, |
| reg_fgrain_glb_en | |
| reg_fgrain_loc_en | |
| reg_block_mode | |
| reg_rev_mode | |
| reg_comp_bits | |
| reg_fmt_mode, |
| 0, 10); |
| VSYNC_WR_MPEG_REG_BITS(fg_reg->fgrain_ctrl, |
| reg_last_in_mode, 14, 1); |
| VSYNC_WR_MPEG_REG_BITS(fg_reg->fgrain_ctrl, |
| reg_fgrain_ext_imode, 16, 1); |
| } |
| |
| static void fgrain_start(u8 layer_id) |
| { |
| u32 reg_fgrain_glb_en = 1 << 0; |
| u32 reg_fgrain_loc_en = 1 << 1; |
| struct hw_fg_reg_s *fg_reg; |
| |
| if (!glayer_info[layer_id].fgrain_support) |
| return; |
| if (glayer_info[layer_id].fgrain_start) |
| return; |
| fg_reg = &vd_layer[layer_id].fg_reg; |
| |
| VSYNC_WR_MPEG_REG_BITS(fg_reg->fgrain_ctrl, |
| reg_fgrain_glb_en | |
| reg_fgrain_loc_en, |
| 0, 2); |
| |
| glayer_info[layer_id].fgrain_start = true; |
| glayer_info[layer_id].fgrain_force_update = true; |
| } |
| |
| static void fgrain_stop(u8 layer_id) |
| { |
| u32 reg_fgrain_glb_en = 1 << 0; |
| u32 reg_fgrain_loc_en = 0 << 1; |
| struct hw_fg_reg_s *fg_reg; |
| |
| if (!glayer_info[layer_id].fgrain_support) |
| return; |
| if (!glayer_info[layer_id].fgrain_start) |
| return; |
| fg_reg = &vd_layer[layer_id].fg_reg; |
| |
| VSYNC_WR_MPEG_REG_BITS(fg_reg->fgrain_ctrl, |
| reg_fgrain_glb_en | |
| reg_fgrain_loc_en, |
| 0, 2); |
| glayer_info[layer_id].fgrain_start = false; |
| } |
| |
| static void fgrain_set_window(u32 layer_id, |
| struct fgrain_setting_s *setting) |
| { |
| struct hw_fg_reg_s *fg_reg; |
| |
| fg_reg = &vd_layer[layer_id].fg_reg; |
| VSYNC_WR_MPEG_REG(fg_reg->fgrain_win_h, |
| (setting->start_x << 0) | |
| (setting->end_x << 16)); |
| VSYNC_WR_MPEG_REG(fg_reg->fgrain_win_v, |
| (setting->start_y << 0) | |
| (setting->end_y << 16)); |
| } |
| |
| static int fgrain_init(u8 layer_id, u32 table_size) |
| { |
| int ret; |
| u32 channel = FILM_GRAIN0_CHAN; |
| struct lut_dma_set_t lut_dma_set; |
| |
| if (!glayer_info[layer_id].fgrain_support) |
| return -1; |
| if (layer_id == 0) |
| channel = FILM_GRAIN0_CHAN; |
| else if (layer_id == 1) |
| channel = FILM_GRAIN1_CHAN; |
| lut_dma_set.channel = channel; |
| lut_dma_set.dma_dir = LUT_DMA_WR; |
| lut_dma_set.irq_source = ENCP_GO_FEILD; |
| lut_dma_set.mode = LUT_DMA_MANUAL; |
| lut_dma_set.table_size = table_size; |
| ret = lut_dma_register(&lut_dma_set); |
| if (ret >= 0) { |
| glayer_info[layer_id].lut_dma_support = 1; |
| |
| } else { |
| pr_info("%s failed, fg not support\n", __func__); |
| glayer_info[layer_id].lut_dma_support = 0; |
| } |
| return ret; |
| } |
| |
| static void fgrain_uninit(u8 layer_id) |
| { |
| u32 channel = FILM_GRAIN0_CHAN; |
| |
| if (!glayer_info[layer_id].fgrain_support) |
| return; |
| |
| if (layer_id == 0) |
| channel = FILM_GRAIN0_CHAN; |
| else if (layer_id == 1) |
| channel = FILM_GRAIN1_CHAN; |
| lut_dma_unregister(LUT_DMA_WR, channel); |
| } |
| |
| static int fgrain_write(u32 layer_id, u32 fgs_table_addr) |
| { |
| int table_size = FGRAIN_TBL_SIZE; |
| u32 channel = 0; |
| |
| if (layer_id == 0) |
| channel = FILM_GRAIN0_CHAN; |
| else if (layer_id == 1) |
| channel = FILM_GRAIN1_CHAN; |
| |
| lut_dma_write_phy_addr(channel, |
| fgs_table_addr, |
| table_size); |
| return 0; |
| } |
| |
| static void fgrain_update_irq_source(u32 layer_id) |
| { |
| u32 irq_source = ENCP_GO_FEILD; |
| u32 viu, channel = 0; |
| |
| viu = READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3; |
| |
| switch (viu) { |
| case 0: |
| irq_source = ENCL_GO_FEILD; |
| break; |
| case 1: |
| irq_source = ENCI_GO_FEILD; |
| break; |
| case 2: |
| irq_source = ENCP_GO_FEILD; |
| break; |
| } |
| if (layer_id == 0) |
| channel = FILM_GRAIN0_CHAN; |
| else if (layer_id == 1) |
| channel = FILM_GRAIN1_CHAN; |
| |
| lut_dma_update_irq_source(channel, irq_source); |
| } |
| |
| void fgrain_config(u8 layer_id, |
| struct vpp_frame_par_s *frame_par, |
| struct mif_pos_s *mif_setting, |
| struct fgrain_setting_s *setting, |
| struct vframe_s *vf) |
| { |
| u32 type; |
| |
| if (!vf || !mif_setting || !setting || !frame_par) |
| return; |
| if (!glayer_info[layer_id].fgrain_support) |
| return; |
| if (!glayer_info[layer_id].lut_dma_support) |
| return; |
| setting->id = layer_id; |
| type = vf->type; |
| if (frame_par->nocomp) |
| type &= ~VIDTYPE_COMPRESS; |
| |
| if (type & VIDTYPE_COMPRESS) { |
| /* 1:afbc mode or 0: non-afbc mode */ |
| setting->afbc = 1; |
| /* bit[2]=0, non-afbc mode */ |
| setting->last_in_mode = 0; |
| /* afbc copress is always 420 */ |
| setting->fmt_mode = 2; |
| setting->used = 1; |
| if (vf->bitdepth & BITDEPTH_Y10) |
| setting->bitdepth = 1; |
| else |
| setting->bitdepth = 0; |
| } else { |
| setting->afbc = 0; |
| setting->last_in_mode = 1; |
| if (type & VIDTYPE_VIU_NV21) { |
| setting->fmt_mode = 2; |
| setting->used = 1; |
| } else { |
| /* only support 420 */ |
| setting->used = 0; |
| } |
| /* fg after mif always 10 bits */ |
| setting->bitdepth = 1; |
| } |
| |
| if (glayer_info[layer_id].reverse) |
| setting->reverse = 3; |
| else |
| setting->reverse = 0; |
| |
| setting->start_x = mif_setting->start_x_lines; |
| setting->end_x = mif_setting->end_x_lines; |
| setting->start_y = mif_setting->start_y_lines; |
| setting->end_y = mif_setting->end_y_lines; |
| if (setting->afbc) { |
| setting->start_x = setting->start_x / 32 * 32; |
| setting->end_x = setting->end_x / 32 * 32; |
| setting->start_y = setting->start_y / 4 * 4; |
| setting->end_y = setting->end_y / 4 * 4; |
| } else { |
| setting->end_x = (setting->end_x >> 1) << 1; |
| setting->end_y = (setting->end_y >> 1) << 1; |
| |
| setting->start_x = (setting->start_x >> 1) << 1; |
| setting->start_y = (setting->start_y >> 1) << 1; |
| } |
| } |
| |
| void fgrain_setting(u8 layer_id, |
| struct fgrain_setting_s *setting, |
| struct vframe_s *vf) |
| { |
| if (!vf || !setting) |
| return; |
| if (!glayer_info[layer_id].lut_dma_support) |
| return; |
| if (!setting->used || !vf->fgs_valid || |
| !glayer_info[layer_id].fgrain_enable) |
| fgrain_stop(layer_id); |
| if (glayer_info[layer_id].fgrain_enable) { |
| if (setting->used && vf->fgs_valid && |
| vf->fgs_table_adr) { |
| fgrain_set_config(setting); |
| fgrain_set_window(layer_id, setting); |
| } |
| } |
| } |
| |
| void fgrain_update_table(u8 layer_id, |
| struct vframe_s *vf) |
| { |
| if (!vf) |
| return; |
| if (!glayer_info[layer_id].lut_dma_support) |
| return; |
| if (!vf->fgs_valid || !glayer_info[layer_id].fgrain_enable) |
| fgrain_stop(layer_id); |
| |
| if (glayer_info[layer_id].fgrain_enable) { |
| if (vf->fgs_valid && vf->fgs_table_adr) { |
| fgrain_start(layer_id); |
| fgrain_update_irq_source(layer_id); |
| fgrain_write(layer_id, vf->fgs_table_adr); |
| } |
| } |
| } |
| |
| #else |
| static int fgrain_init(u8 layer_id, u32 table_size) |
| { |
| pr_info("warning: film grain not support!\n"); |
| return 0; |
| } |
| |
| static void fgrain_uninit(u8 layer_id) |
| { |
| } |
| |
| void fgrain_config(u8 layer_id, |
| struct vpp_frame_par_s *frame_par, |
| struct mif_pos_s *mif_setting, |
| struct fgrain_setting_s *setting, |
| struct vframe_s *vf) |
| { |
| } |
| |
| void fgrain_setting(u8 layer_id, |
| struct fgrain_setting_s *setting, |
| struct vframe_s *vf) |
| { |
| } |
| |
| void fgrain_update_table(u8 layer_id, |
| struct vframe_s *vf) |
| |
| { |
| } |
| #endif |
| |
| /********************************************************* |
| * Init APIs |
| *********************************************************/ |
| static void init_layer_canvas( |
| struct video_layer_s *layer, u32 start_canvas) |
| { |
| u32 i, j; |
| |
| if (!layer) |
| return; |
| |
| for (i = 0; i < CANVAS_TABLE_CNT; i++) { |
| for (j = 0; j < 6; j++) |
| layer->canvas_tbl[i][j] = |
| start_canvas++; |
| layer->disp_canvas[i][0] = |
| (layer->canvas_tbl[i][2] << 16) | |
| (layer->canvas_tbl[i][1] << 8) | |
| layer->canvas_tbl[i][0]; |
| layer->disp_canvas[i][1] = |
| (layer->canvas_tbl[i][5] << 16) | |
| (layer->canvas_tbl[i][4] << 8) | |
| layer->canvas_tbl[i][3]; |
| } |
| } |
| |
| static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, |
| u64 arg2) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc((unsigned long)function_id, |
| (unsigned long)arg0, |
| (unsigned long)arg1, |
| (unsigned long)arg2, |
| 0, 0, 0, 0, &res); |
| return res.a0; |
| } |
| |
| void vpp_probe_en_set(u32 enable) |
| { |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { |
| if (enable) |
| __invoke_psci_fn_smc(0x82000080, 1, 0, 0); |
| else |
| __invoke_psci_fn_smc(0x82000080, 0, 0, 0); |
| } |
| } |
| |
| void video_secure_set(void) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_SECURITY |
| int i; |
| u32 secure_src = 0; |
| u32 secure_enable = 0; |
| struct video_layer_s *layer = NULL; |
| |
| for (i = 0; i < MAX_VD_LAYERS; i++) { |
| layer = &vd_layer[i]; |
| if (layer->dispbuf && |
| (layer->dispbuf->flag & VFRAME_FLAG_VIDEO_SECURE)) |
| secure_enable = 1; |
| else |
| secure_enable = 0; |
| if (layer->dispbuf && |
| secure_enable) { |
| if (layer->layer_id == 0) |
| secure_src |= VD1_INPUT_SECURE; |
| else if (layer->layer_id == 1) |
| secure_src |= VD2_INPUT_SECURE; |
| } |
| } |
| secure_config(VIDEO_MODULE, secure_src); |
| #endif |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_SECURITY |
| void vpp_secure_cb(u32 arg) |
| { |
| pr_debug("%s: arg=%x, reg:%x\n", |
| __func__, |
| arg, |
| READ_VCBUS_REG(VIU_DATA_SEC)); |
| } |
| #endif |
| |
| int video_hw_init(void) |
| { |
| u32 cur_hold_line; |
| int i; |
| |
| if (!legacy_vpp) { |
| WRITE_VCBUS_REG_BITS( |
| VPP_OFIFO_SIZE, 0x1000, |
| VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); |
| WRITE_VCBUS_REG_BITS( |
| VPP_MATRIX_CTRL, 0, 10, 5); |
| } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) |
| WRITE_VCBUS_REG_BITS( |
| VPP_OFIFO_SIZE, 0xfff, |
| VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); |
| |
| WRITE_VCBUS_REG(VPP_PREBLEND_VD1_H_START_END, 4096); |
| WRITE_VCBUS_REG(VPP_BLEND_VD2_H_START_END, 4096); |
| |
| if (is_meson_txl_cpu() || is_meson_txlx_cpu()) { |
| /* fifo max size on txl :128*3=384[0x180] */ |
| WRITE_VCBUS_REG( |
| vd_layer[0].vd_mif_reg.vd_if0_luma_fifo_size, |
| 0x180); |
| WRITE_VCBUS_REG( |
| vd_layer[1].vd_mif_reg.vd_if0_luma_fifo_size, |
| 0x180); |
| } |
| |
| /* default 10bit setting for gxm */ |
| if (is_meson_gxm_cpu()) { |
| WRITE_VCBUS_REG_BITS(VIU_MISC_CTRL1, 0xff, 16, 8); |
| WRITE_VCBUS_REG(VPP_DOLBY_CTRL, 0x22000); |
| /* |
| *default setting is black for dummy data1& dumy data0, |
| *for dummy data1 the y/cb/cr data width is 10bit on gxm, |
| *for dummy data the y/cb/cr data width is 8bit but |
| *vpp_dummy_data will be left shift 2bit auto on gxm!!! |
| */ |
| WRITE_VCBUS_REG(VPP_DUMMY_DATA1, 0x1020080); |
| WRITE_VCBUS_REG(VPP_DUMMY_DATA, 0x42020); |
| } else if (is_meson_txlx_cpu() || |
| cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { |
| /*black 10bit*/ |
| WRITE_VCBUS_REG(VPP_DUMMY_DATA, 0x4080200); |
| } |
| /* temp: enable VPU arb mem */ |
| switch_vpu_mem_pd_vmod(VPU_VPU_ARB, VPU_MEM_POWER_ON); |
| /*disable sr default when power up*/ |
| WRITE_VCBUS_REG(VPP_SRSHARP0_CTRL, 0); |
| WRITE_VCBUS_REG(VPP_SRSHARP1_CTRL, 0); |
| |
| cur_hold_line = READ_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off); |
| cur_hold_line = cur_hold_line & 0xff; |
| |
| if (cur_hold_line > 0x1f) |
| vpp_hold_line = 0x1f; |
| else |
| vpp_hold_line = cur_hold_line; |
| |
| /* Temp force set dmc */ |
| if (!legacy_vpp) { |
| WRITE_DMCREG( |
| DMC_AM0_CHAN_CTRL, |
| 0x8ff403cf); |
| /* for vd1 & vd2 dummy alpha*/ |
| WRITE_VCBUS_REG( |
| VPP_POST_BLEND_DUMMY_ALPHA, |
| 0x7fffffff); |
| WRITE_VCBUS_REG_BITS( |
| VPP_MISC1, 0x100, 0, 9); |
| } |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { |
| /* disable latch for sr core0/1 scaler */ |
| WRITE_VCBUS_REG_BITS( |
| sr_info.sr0_sharp_sync_ctrl, |
| 1, 0, 1); |
| WRITE_VCBUS_REG_BITS( |
| sr_info.sr0_sharp_sync_ctrl, |
| 1, 8, 1); |
| WRITE_VCBUS_REG_BITS( |
| sr_info.sr1_sharp_sync_ctrl, |
| 1, 8, 1); |
| } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { |
| WRITE_VCBUS_REG_BITS( |
| sr_info.sr0_sharp_sync_ctrl, |
| 1, 0, 1); |
| WRITE_VCBUS_REG_BITS( |
| sr_info.sr0_sharp_sync_ctrl, |
| 1, 8, 1); |
| } |
| /* force bypass dolby for TL1/T5, no dolby function */ |
| if (!glayer_info[0].dv_support) |
| WRITE_VCBUS_REG_BITS( |
| DOLBY_PATH_CTRL, 0xf, 0, 6); |
| for (i = 0; i < MAX_VD_LAYER; i++) { |
| if (glayer_info[i].fgrain_support) |
| fgrain_init(i, FGRAIN_TBL_SIZE); |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_SECURITY |
| secure_register(VIDEO_MODULE, 0, |
| VSYNC_WR_MPEG_REG, vpp_secure_cb); |
| #endif |
| return 0; |
| } |
| |
| static int get_sr_core_support(struct amvideo_device_data_s *p_amvideo) |
| { |
| u32 core_support = 0; |
| |
| if ((p_amvideo->sr0_support == 0xff) && |
| (p_amvideo->sr1_support == 0xff)) { |
| /* chip before tm2 revb, used old logic */ |
| if (is_meson_tl1_cpu() || |
| is_meson_tm2_cpu()) |
| core_support = NEW_CORE0_CORE1; |
| else if (is_meson_txhd_cpu() || |
| is_meson_g12a_cpu() || |
| is_meson_g12b_cpu() || |
| is_meson_sm1_cpu()) |
| core_support = ONLY_CORE0; |
| else if (is_meson_gxlx_cpu()) |
| core_support = ONLY_CORE1; |
| else if (is_meson_txlx_cpu() || |
| is_meson_txl_cpu() || |
| is_meson_gxtvbb_cpu()) |
| core_support = OLD_CORE0_CORE1; |
| return core_support; |
| } else if ((p_amvideo->sr0_support == 1) && |
| (p_amvideo->sr1_support == 1)) { |
| core_support = NEW_CORE0_CORE1; |
| } else if (p_amvideo->sr0_support == 1) { |
| core_support = ONLY_CORE0; |
| } else if (p_amvideo->sr1_support == 1) { |
| core_support = ONLY_CORE1; |
| } |
| return core_support; |
| } |
| |
| static void vpp_sr_init(struct amvideo_device_data_s *p_amvideo) |
| { |
| struct sr_info_s *sr; |
| |
| sr = &sr_info; |
| /* sr_info */ |
| if (is_meson_g12a_cpu() || |
| is_meson_g12b_cpu() || |
| is_meson_sm1_cpu()) { |
| sr->sr_reg_offt = 0xc00; |
| sr->sr_reg_offt2 = 0x00; |
| } else if (is_meson_tl1_cpu() || |
| is_meson_tm2_cpu()) { |
| sr->sr_reg_offt = 0xc00; |
| sr->sr_reg_offt2 = 0xc80; |
| } else { |
| sr->sr_reg_offt = 0; |
| sr->sr_reg_offt2 = 0x00; |
| } |
| |
| if (p_amvideo->sr_reg_offt != 0xff) { |
| sr->sr_reg_offt = p_amvideo->sr_reg_offt; |
| sr->sr0_sharp_sync_ctrl = |
| TM2REVB_SRSHARP0_SHARP_SYNC_CTRL; |
| } else { |
| sr->sr0_sharp_sync_ctrl = |
| SRSHARP0_SHARP_SYNC_CTRL; |
| } |
| if (p_amvideo->sr_reg_offt != 0xff) { |
| sr->sr_reg_offt2 = p_amvideo->sr_reg_offt2; |
| sr->sr1_sharp_sync_ctrl = |
| TM2REVB_SRSHARP1_SHARP_SYNC_CTRL; |
| } else { |
| sr->sr1_sharp_sync_ctrl = |
| SRSHARP1_SHARP_SYNC_CTRL; |
| } |
| |
| if ((p_amvideo->sr0_support == 0xff) && |
| (p_amvideo->sr1_support == 0xff)) { |
| if (is_meson_gxlx_cpu()) { |
| sr->sr_support &= ~SUPER_CORE0_SUPPORT; |
| sr->sr_support |= SUPER_CORE1_SUPPORT; |
| sr->core1_v_disable_width_max = 4096; |
| sr->core1_v_enable_width_max = 2048; |
| } else if (is_meson_txhd_cpu()) { |
| /* 2k pannal */ |
| sr->sr_support |= SUPER_CORE0_SUPPORT; |
| sr->sr_support &= ~SUPER_CORE1_SUPPORT; |
| sr->core0_v_disable_width_max = 2048; |
| sr->core0_v_enable_width_max = 1024; |
| } else if (is_meson_g12a_cpu() || |
| is_meson_g12b_cpu() || |
| is_meson_sm1_cpu()) { |
| sr->sr_support |= SUPER_CORE0_SUPPORT; |
| sr->sr_support &= ~SUPER_CORE1_SUPPORT; |
| sr->core0_v_disable_width_max = 4096; |
| sr->core0_v_enable_width_max = 2048; |
| } else if (is_meson_gxtvbb_cpu() || |
| is_meson_txl_cpu() || |
| is_meson_txlx_cpu() || |
| is_meson_tl1_cpu() || |
| is_meson_tm2_cpu()) { |
| sr->sr_support |= SUPER_CORE0_SUPPORT; |
| sr->sr_support |= SUPER_CORE1_SUPPORT; |
| sr->core0_v_disable_width_max = 2048; |
| sr->core0_v_enable_width_max = 1024; |
| sr->core1_v_disable_width_max = 4096; |
| sr->core1_v_enable_width_max = 2048; |
| } else { |
| sr->sr_support &= ~SUPER_CORE0_SUPPORT; |
| sr->sr_support &= ~SUPER_CORE1_SUPPORT; |
| } |
| } else { |
| if (p_amvideo->sr0_support == 1) { |
| sr->sr_support |= SUPER_CORE0_SUPPORT; |
| sr->core0_v_disable_width_max = |
| p_amvideo->core_v_disable_width_max[0]; |
| sr->core0_v_enable_width_max = |
| p_amvideo->core_v_enable_width_max[0]; |
| } |
| if (p_amvideo->sr1_support == 1) { |
| sr->sr_support |= SUPER_CORE1_SUPPORT; |
| sr->core1_v_disable_width_max = |
| p_amvideo->core_v_disable_width_max[1]; |
| sr->core1_v_enable_width_max = |
| p_amvideo->core_v_enable_width_max[1]; |
| } |
| } |
| sr->supscl_path = p_amvideo->supscl_path; |
| sr->core_support = get_sr_core_support(p_amvideo); |
| } |
| |
| int video_early_init(struct amvideo_device_data_s *p_amvideo) |
| { |
| int r = 0, i; |
| |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) |
| legacy_vpp = false; |
| |
| /* check super scaler support status */ |
| vpp_sr_init(p_amvideo); |
| /* adaptive config bypass ratio */ |
| vpp_bypass_ratio_config(); |
| |
| memset(vd_layer, 0, sizeof(vd_layer)); |
| for (i = 0; i < MAX_VD_LAYER; i++) { |
| vd_layer[i].layer_id = i; |
| vd_layer[i].cur_canvas_id = 0; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| vd_layer[i].next_canvas_id = 1; |
| #endif |
| /* vd_layer[i].global_output = 1; */ |
| vd_layer[i].keep_frame_id = 0xff; |
| vd_layer[i].disable_video = VIDEO_DISABLE_FORNEXT; |
| |
| /* clip config */ |
| vd_layer[i].clip_setting.id = i; |
| vd_layer[i].clip_setting.misc_reg_offt = cur_dev->vpp_off; |
| vd_layer[i].clip_setting.clip_max = 0x3fffffff; |
| vd_layer[i].clip_setting.clip_min = 0; |
| vd_layer[i].clip_setting.clip_done = true; |
| |
| vpp_disp_info_init(&glayer_info[i], i); |
| memset(&gpic_info[i], 0, sizeof(struct vframe_pic_mode_s)); |
| glayer_info[i].wide_mode = 1; |
| glayer_info[i].zorder = reference_zorder - 2 + i; |
| glayer_info[i].cur_sel_port = i; |
| glayer_info[i].last_sel_port = i; |
| glayer_info[i].display_path_id = VFM_PATH_DEF; |
| glayer_info[i].need_no_compress = false; |
| if (legacy_vpp) { |
| glayer_info[i].afbc_support = true; |
| glayer_info[i].pps_support = |
| (i == 0) ? true : false; |
| } else if (is_meson_tl1_cpu()) { |
| glayer_info[i].afbc_support = |
| (i == 0) ? true : false; |
| glayer_info[i].pps_support = |
| (i == 0) ? true : false; |
| /* force bypass dolby for TL1/T5, no dolby function */ |
| p_amvideo->dv_support = 0; |
| } else if (is_meson_tm2_cpu()) { |
| glayer_info[i].afbc_support = |
| (i == 0) ? true : false; |
| glayer_info[i].pps_support = true; |
| } else if (is_meson_g12a_cpu() || |
| is_meson_g12b_cpu() || |
| is_meson_sm1_cpu()) { |
| glayer_info[i].afbc_support = true; |
| glayer_info[i].pps_support = true; |
| } else { |
| /* after tm2 revb */ |
| glayer_info[i].afbc_support = |
| p_amvideo->afbc_support[i]; |
| glayer_info[i].pps_support = |
| p_amvideo->pps_support[i]; |
| } |
| if (p_amvideo->dv_support) |
| glayer_info[i].dv_support = true; |
| else |
| glayer_info[i].dv_support = false; |
| if (p_amvideo->fgrain_support[i]) { |
| glayer_info[i].fgrain_support = true; |
| glayer_info[i].fgrain_enable = true; |
| } else { |
| glayer_info[i].fgrain_support = false; |
| glayer_info[i].fgrain_enable = false; |
| } |
| glayer_info[i].alpha_support = p_amvideo->alpha_support[i]; |
| hscaler_8tap_enable[i] = has_hscaler_8tap(i); |
| pre_hscaler_ntap_enable[i] = has_pre_hscaler_ntap(i); |
| pre_vscaler_ntap_enable[i] = has_pre_vscaler_ntap(i); |
| pre_hscaler_ntap_set[i] = 0xff; |
| pre_vscaler_ntap_set[i] = 0xff; |
| } |
| |
| /* only enable vd1 as default */ |
| vd_layer[0].global_output = 1; |
| vd_layer[0].misc_reg_offt = 0 + cur_dev->vpp_off; |
| vd_layer[1].misc_reg_offt = 0 + cur_dev->vpp_off; |
| if (is_meson_sc2_cpu()) { |
| memcpy(&vd_layer[0].vd_afbc_reg, |
| &vd_afbc_reg_sc2_array[0], |
| sizeof(struct hw_afbc_reg_s)); |
| memcpy(&vd_layer[1].vd_afbc_reg, |
| &vd_afbc_reg_sc2_array[1], |
| sizeof(struct hw_afbc_reg_s)); |
| memcpy(&vd_layer[0].vd_mif_reg, |
| &vd_mif_reg_sc2_array[0], |
| sizeof(struct hw_vd_reg_s)); |
| memcpy(&vd_layer[1].vd_mif_reg, |
| &vd_mif_reg_sc2_array[1], |
| sizeof(struct hw_vd_reg_s)); |
| memcpy(&vd_layer[0].fg_reg, |
| &fg_reg_sc2_array[0], |
| sizeof(struct hw_fg_reg_s)); |
| memcpy(&vd_layer[1].fg_reg, |
| &fg_reg_sc2_array[1], |
| sizeof(struct hw_fg_reg_s)); |
| } else { |
| memcpy(&vd_layer[0].vd_afbc_reg, |
| &vd_afbc_reg_array[0], |
| sizeof(struct hw_afbc_reg_s)); |
| memcpy(&vd_layer[1].vd_afbc_reg, |
| &vd_afbc_reg_array[1], |
| sizeof(struct hw_afbc_reg_s)); |
| if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { |
| memcpy(&vd_layer[0].vd_mif_reg, |
| &vd_mif_reg_g12_array[0], |
| sizeof(struct hw_vd_reg_s)); |
| memcpy(&vd_layer[1].vd_mif_reg, |
| &vd_mif_reg_g12_array[1], |
| sizeof(struct hw_vd_reg_s)); |
| if (is_meson_tm2_revb()) { |
| memcpy(&vd_layer[0].fg_reg, |
| &fg_reg_g12_array[0], |
| sizeof(struct hw_fg_reg_s)); |
| memcpy(&vd_layer[1].fg_reg, |
| &fg_reg_g12_array[1], |
| sizeof(struct hw_fg_reg_s)); |
| } |
| } else { |
| memcpy(&vd_layer[0].vd_mif_reg, |
| &vd_mif_reg_legacy_array[0], |
| sizeof(struct hw_vd_reg_s)); |
| memcpy(&vd_layer[1].vd_mif_reg, |
| &vd_mif_reg_legacy_array[1], |
| sizeof(struct hw_vd_reg_s)); |
| } |
| } |
| vd_layer[0].layer_alpha = 0x100; |
| |
| /* g12a has no alpha overflow check in hardware */ |
| vd_layer[1].layer_alpha = legacy_vpp ? 0x1ff : 0x100; |
| |
| INIT_WORK(&vpu_delay_work, do_vpu_delay_work); |
| |
| init_layer_canvas(&vd_layer[0], LAYER1_CANVAS_BASE_INDEX); |
| init_layer_canvas(&vd_layer[1], LAYER2_CANVAS_BASE_INDEX); |
| return r; |
| } |
| |
| int video_late_uninit(void) |
| { |
| int i; |
| |
| for (i = 0; i < MAX_VD_LAYER; i++) |
| fgrain_uninit(i); |
| return 0; |
| } |
| |
| MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n"); |
| module_param(vpp_hold_line, uint, 0664); |
| |
| MODULE_PARM_DESC(bypass_cm, "\n bypass_cm\n"); |
| module_param(bypass_cm, bool, 0664); |
| |
| MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n"); |
| module_param(reference_zorder, uint, 0664); |
| |
| MODULE_PARM_DESC(video_mute_on, "\n video_mute_on\n"); |
| module_param(video_mute_on, bool, 0664); |
| |
| module_param(disable_sr_threshold, uint, 0664); |
| MODULE_PARM_DESC(disable_sr_threshold, "disable_sr_threshold"); |