author | Jian Cao <jian.cao@amlogic.com> | 2019-05-29 09:10:45 (GMT) |
---|---|---|
committer | Jianxin Pan <jianxin.pan@amlogic.com> | 2019-05-31 05:05:45 (GMT) |
commit | b58fe13d0eb92c25af49131299de9e3a796dc97e (patch) | |
tree | 1f28fb8bfa3da895dce098a536fb2e234e251b21 | |
parent | 41de7c30dfe3df6fcfe6b08568a628174afaf6a9 (diff) | |
download | common-bringup/amlogic-4.19/g12a.zip common-bringup/amlogic-4.19/g12a.tar.gz common-bringup/amlogic-4.19/g12a.tar.bz2 |
video: add video_sink support [1/1]
PD#SWPL-9026
Problem:
add video_sink support for kernel 4.19
Solution:
porting driver code
Verify:
verified on g12a-u200
Change-Id: I92357f58dce71fd037c200c1c2573e39a980d686
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
26 files changed, 18222 insertions, 76 deletions
diff --git a/arch/arm/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm/boot/dts/amlogic/meson-g12a.dtsi index 35fc9e9..fabe096 100644 --- a/arch/arm/boot/dts/amlogic/meson-g12a.dtsi +++ b/arch/arm/boot/dts/amlogic/meson-g12a.dtsi @@ -1292,6 +1292,14 @@ memory-region = <&ion_cma_reserved>; }; + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + codec_io: codec_io { compatible = "amlogic, meson-g12a, codec-io"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm/boot/dts/amlogic/meson-sm1.dtsi index 61efbe0..cd1fc0b 100644 --- a/arch/arm/boot/dts/amlogic/meson-sm1.dtsi +++ b/arch/arm/boot/dts/amlogic/meson-sm1.dtsi @@ -1370,6 +1370,14 @@ memory-region = <&ion_cma_reserved>; }; + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + codec_io: codec_io { compatible = "amlogic, meson-g12a, codec-io"; status = "okay"; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 458881d..8f1e553 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -516,6 +516,7 @@ CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA=y CONFIG_AMLOGIC_MEDIA_CODEC_MM=y CONFIG_AMLOGIC_MEDIA_VFM=y CONFIG_AMLOGIC_VIDEOBUF_RESOURCE=y +CONFIG_AMLOGIC_MEDIA_VIDEO=y CONFIG_AMLOGIC_VOUT=y CONFIG_AMLOGIC_VOUT_SERVE=y CONFIG_AMLOGIC_VOUT2_SERVE=y diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi index 31c9304..06fd2de 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi @@ -1304,6 +1304,14 @@ memory-region = <&ion_cma_reserved>; }; + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + codec_io: codec_io { compatible = "amlogic, meson-g12a, codec-io"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi index 6949ced..2f94986 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi @@ -1366,6 +1366,14 @@ memory-region = <&ion_cma_reserved>; }; + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + codec_io: codec_io { compatible = "amlogic, meson-g12a, codec-io"; status = "okay"; diff --git a/arch/arm64/configs/meson64_a64_defconfig b/arch/arm64/configs/meson64_a64_defconfig index 32a71db..9bd1a30 100644 --- a/arch/arm64/configs/meson64_a64_defconfig +++ b/arch/arm64/configs/meson64_a64_defconfig @@ -478,6 +478,7 @@ CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA=y CONFIG_AMLOGIC_MEDIA_CODEC_MM=y CONFIG_AMLOGIC_MEDIA_VFM=y CONFIG_AMLOGIC_VIDEOBUF_RESOURCE=y +CONFIG_AMLOGIC_MEDIA_VIDEO=y CONFIG_AMLOGIC_VOUT=y CONFIG_AMLOGIC_VOUT_SERVE=y CONFIG_AMLOGIC_VOUT2_SERVE=y diff --git a/drivers/amlogic/media/Kconfig b/drivers/amlogic/media/Kconfig index a7fec01..d6ceebb 100644 --- a/drivers/amlogic/media/Kconfig +++ b/drivers/amlogic/media/Kconfig @@ -80,6 +80,7 @@ source "drivers/amlogic/media/common/Kconfig" endif if AMLOGIC_MEDIA_DRIVERS +source "drivers/amlogic/media/video_sink/Kconfig" source "drivers/amlogic/media/vout/Kconfig" source "drivers/amlogic/media/osd/Kconfig" source "drivers/amlogic/media/frame_sync/Kconfig" diff --git a/drivers/amlogic/media/Makefile b/drivers/amlogic/media/Makefile index 5911af8..a619ae1 100644 --- a/drivers/amlogic/media/Makefile +++ b/drivers/amlogic/media/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_AMLOGIC_MEDIA_COMMON) += common/ +obj-$(CONFIG_AMLOGIC_MEDIA_VIDEO) += video_sink/ obj-$(CONFIG_AMLOGIC_MEDIA_FB) += osd/ obj-$(CONFIG_AMLOGIC_VOUT) += vout/ obj-$(CONFIG_AMLOGIC_MEDIA_FRAME_SYNC) += frame_sync/ diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index 76673b0..0136077 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -303,7 +303,7 @@ static unsigned int vpu_vmod_clk_get(unsigned int vmod) return vpu_clk; } -static int vpu_vmod_clk_request(unsigned int vclk, unsigned int vmod) +int vpu_vmod_clk_request(unsigned int vclk, unsigned int vmod) { int ret = 0; #ifdef CONFIG_VPU_DYNAMIC_ADJ @@ -352,7 +352,7 @@ static int vpu_vmod_clk_request(unsigned int vclk, unsigned int vmod) return ret; } -static int vpu_vmod_clk_release(unsigned int vmod) +int vpu_vmod_clk_release(unsigned int vmod) { int ret = 0; #ifdef CONFIG_VPU_DYNAMIC_ADJ @@ -388,7 +388,7 @@ static int vpu_vmod_clk_release(unsigned int vmod) return ret; } -static void vpu_vmod_mem_pd_switch(unsigned int vmod, int flag) +void vpu_vmod_mem_pd_switch(unsigned int vmod, int flag) { unsigned long flags = 0; unsigned int _val, _reg, _bit, _len; diff --git a/drivers/amlogic/media/frame_sync/timestamp.c b/drivers/amlogic/media/frame_sync/timestamp.c index e22df9e..c16f42f 100644 --- a/drivers/amlogic/media/frame_sync/timestamp.c +++ b/drivers/amlogic/media/frame_sync/timestamp.c @@ -129,6 +129,12 @@ u32 timestamp_pcrscr_get(void) } EXPORT_SYMBOL(timestamp_pcrscr_get); +u32 timestamp_get_pcrlatency(void) +{ + return pcrscr_lantcy; +} +EXPORT_SYMBOL(timestamp_get_pcrlatency); + u32 timestamp_tsdemux_pcr_get(void) { if (tsdemux_pcrscr_get_cb) diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index ebc3550..d0e6b77 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -1154,6 +1154,28 @@ int tsync_set_startsync_mode(int mode) } EXPORT_SYMBOL(tsync_set_startsync_mode); +bool tsync_check_vpts_discontinuity(unsigned int vpts) +{ + unsigned int systemtime; + + if (tsync_get_mode() != TSYNC_MODE_PCRMASTER) + return false; + if (tsync_pcr_demux_pcr_used() == 0) + systemtime = timestamp_pcrscr_get(); + else + systemtime = timestamp_pcrscr_get() + + timestamp_get_pcrlatency(); + if (vpts > systemtime && + (vpts - systemtime) > tsync_vpts_discontinuity_margin()) + return true; + else if (systemtime > vpts && + (systemtime - vpts) > tsync_vpts_discontinuity_margin()) + return true; + else + return false; +} +EXPORT_SYMBOL(tsync_check_vpts_discontinuity); + static ssize_t pcr_recover_store(struct class *class, struct class_attribute *attr, const char *buf, size_t size) diff --git a/drivers/amlogic/media/video_sink/Kconfig b/drivers/amlogic/media/video_sink/Kconfig new file mode 100644 index 0000000..db6c2f9 --- a/dev/null +++ b/drivers/amlogic/media/video_sink/Kconfig @@ -0,0 +1,39 @@ +# +# Amlogic video Sink configuration +# + +menu "Amlogic Video Sink Driver Support" + +config AMLOGIC_MEDIA_VIDEO + bool "Amlogic Video Sink Driver" + default n + help + Amlogic Video Sink module support. + This module driver include basic + video, vpp etc. + Select to enable Amlogic video sink. + +if AMLOGIC_MEDIA_VIDEO + +config AMLOGIC_MEDIA_VSYNC_RDMA + bool "VSYNC CBUS RDMA" + default n + depends on AMLOGIC_MEDIA_RDMA + help + This option is used to configure Amlogic drivers + of the multimedia RDMA VSYNC function, + it as the basis for drivers of the multimedia, + mainly on the operation of the RDMA. + Select to enable RDMA VSYNC. +endif + +config AMLOGIC_VIDEOCAPTURE + bool "Amlogic Video Capture support" + default n + help + This module provides screen capture function + by v4l interface + This module can get YUV data from vdin + This module can provide processed data to upper layer + +endmenu diff --git a/drivers/amlogic/media/video_sink/Makefile b/drivers/amlogic/media/video_sink/Makefile new file mode 100644 index 0000000..7f5a423 --- a/dev/null +++ b/drivers/amlogic/media/video_sink/Makefile @@ -0,0 +1,2 @@ +obj-y += amvideo.o +amvideo-objs += video.o video_keeper.o vpp.o diff --git a/drivers/amlogic/media/video_sink/amvideocap_priv.h b/drivers/amlogic/media/video_sink/amvideocap_priv.h new file mode 100644 index 0000000..aaa34934 --- a/dev/null +++ b/drivers/amlogic/media/video_sink/amvideocap_priv.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * drivers/amlogic/media/video_sink/amvideocap_priv.h + * + * 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. + * + */ + +#ifndef AMVIDEOCAP_PRIV_HHH +#define AMVIDEOCAP_PRIV_HHH +#include <linux/amlogic/media/video_sink/amvideocap.h> +#include <linux/amlogic/media/vfm/vframe.h> + +struct video_frame_info { + int at_flags; + int width; + int height; + int fmt; + int width_aligned; + int byte_per_pix; + u64 timestamp_ms; +}; + +struct src_cap_rect { + int x; + int y; + int width; + int height; +}; + +struct amvideocap_private { + int flags; + int buf_size; + unsigned long phyaddr; + u8 *vaddr; + enum amvideocap_state state; + int sended_end_frame_cap_req; + int wait_max_ms; + + struct video_frame_info src; + struct video_frame_info want; + struct video_frame_info out; + struct src_cap_rect src_rect; +}; + +struct amvideocap_req_data { + struct amvideocap_private *privdata; +}; + +struct amvideocap_req { + int (*callback)(unsigned long data, struct vframe_s *vfput, + int index); + unsigned long data; + int at_flags; /*AT_ */ + u64 timestamp_ms; +}; + +s32 amvideocap_register_memory(unsigned char *phybufaddr, int phybufsize); + +#endif diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c new file mode 100644 index 0000000..3f0e6d8 --- a/dev/null +++ b/drivers/amlogic/media/video_sink/video.c @@ -0,0 +1,13311 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * drivers/amlogic/media/video_sink/video.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/frame_sync/ptsserv.h> +#include <linux/amlogic/media/frame_sync/timestamp.h> +#include <linux/amlogic/media/frame_sync/tsync.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/debugfs.h> +#include <linux/of_device.h> +#include <linux/amlogic/media/canvas/canvas.h> +#include <linux/amlogic/media/canvas/canvas_mgr.h> +#include <linux/dma-mapping.h> +#include <linux/dma-contiguous.h> +#include <linux/sched.h> +#include <linux/sched/clock.h> +#include <linux/amlogic/media/video_sink/video_keeper.h> +#include "video_priv.h" +#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO + +#if defined(CONFIG_AMLOGIC_DEBUG_ATRACE) +#include <trace/events/meson_atrace.h> +#endif + +#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) +#include <linux/amlogic/media/amvecm/amvecm.h> +#endif +#include <linux/amlogic/media/utils/vdec_reg.h> + +#ifdef CONFIG_PM +#include <linux/delay.h> +#include <linux/pm.h> +#endif + +#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" +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE +#include "amvideocap_priv.h" +#endif +#ifdef CONFIG_AM_VIDEO_LOG +#define AMLOG +#endif +#include <linux/amlogic/media/utils/amlog.h> +MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); + +#include <linux/amlogic/media/video_sink/vpp.h> +#include <linux/amlogic/media/vin/tvin/tvin_v4l2.h> +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +#define DISPLAY_CANVAS_BASE_INDEX2 0x10 +#define DISPLAY_CANVAS_MAX_INDEX2 0x15 +#include "../common/rdma/rdma.h" +#endif +#include <linux/amlogic/media/video_sink/video.h> +#include <linux/amlogic/media/codec_mm/configs.h> +#include <linux/amlogic/media/codec_mm/codec_mm.h> + +#include "../common/vfm/vfm.h" + +#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) +#include <linux/amlogic/media/amdolbyvision/dolby_vision.h> +#endif + +#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND +#include <linux/amlogic/pm.h> +#endif + +#define VIDEO_PIP + +static u32 osd_vpp_misc; +static u32 osd_vpp_misc_mask; +static bool update_osd_vpp_misc; +int video_vsync = -ENXIO; +/*global video manage cmd. */ + +static bool legacy_vpp = true; + +#define DEBUG_TMP 0 + +static int video_global_output = 1; +/* video_pause_global: 0 is play, 1 is pause, 2 is invalid */ +static int video_pause_global = 1; + +static u32 cur_omx_index; + +#ifdef CONFIG_GE2D_KEEP_FRAME +/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* #include <mach/mod_gate.h> */ +/* #endif */ +/* #include "mach/meson-secure.h" */ +#endif + +/*TODO for logo*/ +struct platform_resource_s { + char name[10]; + int mem_start; + int mem_end; +}; + +struct video_frame_detect_s { + u32 interrupt_count; + u32 start_receive_count; +}; + +static int debugflags; +static int output_fps; +static u32 omx_pts; +static u32 omx_pts_set_index; +static bool omx_run; +static u32 omx_version = 3; +#define OMX_PTS_DV_DEFAULT_UPPER 2500 +#define OMX_PTS_DV_DEFAULT_LOWER -1600 +static int omx_pts_interval_upper = 11000; +static int omx_pts_interval_lower = -5500; +static int omx_pts_dv_upper = OMX_PTS_DV_DEFAULT_UPPER; +static int omx_pts_dv_lower = OMX_PTS_DV_DEFAULT_LOWER; +static int omx_pts_set_from_hwc_count; +static bool omx_check_previous_session; +static u32 omx_cur_session = 0xffffffff; +static int drop_frame_count; +#define OMX_MAX_COUNT_RESET_SYSTEMTIME 2 +static int receive_frame_count; +static int display_frame_count; +static int omx_need_drop_frame_num; +static bool omx_drop_done; +static bool video_start_post; +static bool videopeek; +static bool nopostvideostart; +static struct video_frame_detect_s video_frame_detect; +static struct timeval time_setomxpts = { + .tv_sec = 0, + .tv_usec = 0, +}; + + +/*----omx_info bit0: keep_last_frame, bit1~31: unused----*/ +static u32 omx_info = 0x1; + +#define ENABLE_UPDATE_HDR_FROM_USER 0 +#if ENABLE_UPDATE_HDR_FROM_USER +static struct vframe_master_display_colour_s vf_hdr; +static bool has_hdr_info; +#endif +static DEFINE_MUTEX(omx_mutex); + +#define DURATION_GCD 750 + +static bool bypass_cm; + +static bool bypass_pps = true; +/*For 3D usage ----0: mbx 1: tv */ +bool platform_type = 1; + +/* for bit depth setting. */ +int bit_depth_flag = 8; + +bool omx_secret_mode; +#define DEBUG_FLAG_FFPLAY (1<<0) +#define DEBUG_FLAG_CALC_PTS_INC (1<<1) + +#define RECEIVER_NAME "amvideo" + +static s32 amvideo_poll_major; +/*static s8 dolby_first_delay;*/ /* for bug 145902 */ + +static int video_receiver_event_fun(int type, void *data, void *); + +static const struct vframe_receiver_op_s video_vf_receiver = { + .event_cb = video_receiver_event_fun +}; + +static struct vframe_receiver_s video_vf_recv; + +#ifdef VIDEO_PIP +#define RECEIVERPIP_NAME "videopip" +static int pip_receiver_event_fun(int type, void *data, void *); + +static const struct vframe_receiver_op_s videopip_vf_receiver = { + .event_cb = pip_receiver_event_fun +}; + +static struct vframe_receiver_s videopip_vf_recv; + +static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par; +static struct vpp_frame_par_s pip_frame_parms[2]; +static struct vframe_s *cur_pipbuf; +static struct vframe_s local_pip; +//int _videopip_set_disable(u32 val); +#endif + +static struct device *amvideo_dev; +static struct device *amvideo_poll_dev; + +static u32 cur_width; +static u32 cur_height; + +#define DRIVER_NAME "amvideo" +#define MODULE_NAME "amvideo" +#define DEVICE_NAME "amvideo" + +#ifdef CONFIG_AML_VSYNC_FIQ_ENABLE +#define FIQ_VSYNC +#endif + +/* #define SLOW_SYNC_REPEAT */ +/* #define INTERLACE_FIELD_MATCH_PROCESS */ +bool disable_slow_sync; + +#ifdef INTERLACE_FIELD_MATCH_PROCESS +#define FIELD_MATCH_THRESHOLD 10 +static int field_matching_count; +#endif + +#define M_PTS_SMOOTH_MAX 45000 +#define M_PTS_SMOOTH_MIN 2250 +#define M_PTS_SMOOTH_ADJUST 900 +static u32 underflow; +static u32 next_peek_underflow; + +#define VIDEO_ENABLE_STATE_IDLE 0 +#define VIDEO_ENABLE_STATE_ON_REQ 1 +#define VIDEO_ENABLE_STATE_ON_PENDING 2 +#define VIDEO_ENABLE_STATE_OFF_REQ 3 + +static DEFINE_SPINLOCK(video_onoff_lock); +static int video_onoff_state = VIDEO_ENABLE_STATE_IDLE; +static u32 video_onoff_time; +static DEFINE_SPINLOCK(video2_onoff_lock); +static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; +static u32 frame_skip_check_cnt; + + +/*frame_detect_flag: 1 enable, 0 disable */ +/*frame_detect_time: */ +/* How often "frame_detect_receive_count" and */ +/* "frame_detect_drop_count" are updated, suggested set 1(s) */ +/*frame_detect_fps: Set fps based on the video file, */ +/* If the FPS is 60, set it to 60000. */ +/*frame_detect_receive_count: */ +/* The number of frame that should be obtained during the test time. */ +/*frame_detect_drop_count: */ +/* The number of frame lost during test time. */ + + +static u32 frame_detect_flag; +static u32 frame_detect_time = 1; +static u32 frame_detect_fps = 60000; +static u32 frame_detect_receive_count; +static u32 frame_detect_drop_count; + +static u32 vpp_hold_setting_cnt; + +#ifdef FIQ_VSYNC +#define BRIDGE_IRQ INT_TIMER_C +#define BRIDGE_IRQ_SET() WRITE_CBUS_REG(ISA_TIMERC, 1) +#endif + +#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); \ + vpu_vmod_mem_pd_switch(VPU_VIU_VD1, VPU_MEM_POWER_ON); \ + vpu_vmod_mem_pd_switch(VPU_AFBC_DEC, VPU_MEM_POWER_ON); \ + vpu_vmod_mem_pd_switch(VPU_DI_POST, VPU_MEM_POWER_ON); \ + if (!legacy_vpp) \ + vpu_vmod_mem_pd_switch( \ + VPU_VD1_SCALE, VPU_MEM_POWER_ON); \ + } while (0) +#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); \ + vpu_vmod_mem_pd_switch(VPU_VIU_VD2, VPU_MEM_POWER_ON); \ + vpu_vmod_mem_pd_switch(VPU_AFBC_DEC1, VPU_MEM_POWER_ON); \ + if (!legacy_vpp) \ + vpu_vmod_mem_pd_switch( \ + VPU_VD2_SCALE, 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 (video_onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ + video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + video_enabled = 1; \ + video_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); \ + video_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ + video_enabled = 0; \ + video_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 (video2_onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ + video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + video2_enabled = 1; \ + video2_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); \ + video2_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ + video2_enabled = 0; \ + video2_status_saved = 0; \ + spin_unlock_irqrestore(&video2_onoff_lock, flags); \ + } while (0) + +#define EnableVideoLayer() \ + do { \ + VD1_MEM_POWER_ON(); \ + VIDEO_LAYER_ON(); \ + } while (0) + +#define EnableVideoLayer2() \ + do { \ + VD2_MEM_POWER_ON(); \ + VIDEO_LAYER2_ON(); \ + } while (0) + +#define VSYNC_EnableVideoLayer2() \ + do { \ + VD2_MEM_POWER_ON(); \ + VSYNC_WR_MPEG_REG(VPP_MISC + cur_dev->vpp_off, \ + READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) |\ + VPP_VD2_PREBLEND | (0x1ff << VPP_VD2_ALPHA_BIT)); \ + } while (0) + +#define DisableVideoLayer() \ + do { \ + 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 + cur_dev->vpp_off, 0); \ + } \ + WRITE_VCBUS_REG(AFBC_ENABLE, 0);\ + VIDEO_LAYER_OFF(); \ + VD1_MEM_POWER_OFF(); \ + if (debug_flag & DEBUG_FLAG_BLACKOUT) { \ + pr_info("DisableVideoLayer()\n"); \ + } \ + } while (0) + +#define DisableVideoLayer_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 + cur_dev->vpp_off, 0); \ + } \ + WRITE_VCBUS_REG(AFBC_ENABLE, 0);\ + if (debug_flag & DEBUG_FLAG_BLACKOUT) { \ + pr_info("DisableVideoLayer_NoDelay()\n"); \ + } \ + } while (0) + +#define DisableVideoLayer2() \ + do { \ + CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ + VPP_VD2_POSTBLEND | VPP_VD2_PREBLEND); \ + VIDEO_LAYER2_OFF(); \ + VD2_MEM_POWER_OFF(); \ + } while (0) + +#define DisableVideoLayer_PREBELEND() \ + do { CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ + VPP_VD1_PREBLEND | VPP_VD2_PREBLEND); \ + WRITE_VCBUS_REG(AFBC_ENABLE, 0);\ + if (debug_flag & DEBUG_FLAG_BLACKOUT) { \ + pr_info("DisableVideoLayer_PREBELEND()\n"); \ + } \ + } while (0) + +/*********************************************************/ +#if DEBUG_TMP +static struct switch_dev video1_state_sdev = { +/* android video layer switch device */ + .name = "video_layer1", +}; +#endif + +static DEFINE_MUTEX(video_layer_mutex); + +static u32 layer_cap; + +static struct disp_info_s glayer_info[MAX_VD_LAYERS]; +static struct vframe_pic_mode_s gPic_info[MAX_VD_LAYERS]; + +static u32 reference_zorder = 128; + +/* default value 20 30 */ +static s32 black_threshold_width = 20; +static s32 black_threshold_height = 30; + +static struct vframe_s hist_test_vf; +static bool hist_test_flag; +static unsigned long hist_buffer_addr; +static u32 hist_print_count; + +#define MAX_ZOOM_RATIO 300 + +#define VPP_PREBLEND_VD_V_END_LIMIT 2304 + +#define DUR2PTS(x) ((x) - ((x) >> 4)) +#define DUR2PTS_RM(x) ((x) & 0xf) +#define PTS2DUR(x) (((x) << 4) / 15) + +#ifdef VIDEO_PTS_CHASE +static int vpts_chase; +static int av_sync_flag; +static int vpts_chase_counter; +static int vpts_chase_pts_diff; +#endif + +static int step_enable; +static int step_flag; + +/*seek values on.video_define.h*/ +static int debug_flag; +int get_video_debug_flags(void) +{ + return debug_flag; +} + +/* DEBUG_FLAG_BLACKOUT; */ + +static int vsync_enter_line_max; +static int vsync_exit_line_max; + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +static int vsync_rdma_line_max; +#endif +static u32 framepacking_support __nosavedata; +static unsigned int framepacking_width = 1920; +static unsigned int framepacking_height = 2205; +static unsigned int framepacking_blank = 45; +static unsigned int process_3d_type; +static unsigned int last_process_3d_type; +#ifdef TV_3D_FUNCTION_OPEN +/* toggle_3d_fa_frame is for checking the vpts_expire in 2 vsnyc */ +static int toggle_3d_fa_frame = 1; +/*the pause_one_3d_fl_frame is for close*/ +/*the A/B register switch in every sync at pause mode. */ +static int pause_one_3d_fl_frame; +MODULE_PARM_DESC(pause_one_3d_fl_frame, "\n pause_one_3d_fl_frame\n"); +module_param(pause_one_3d_fl_frame, uint, 0664); + +/*debug info control for skip & repeate vframe case*/ +static unsigned int video_dbg_vf; +MODULE_PARM_DESC(video_dbg_vf, "\n video_dbg_vf\n"); +module_param(video_dbg_vf, uint, 0664); + +static unsigned int video_get_vf_cnt; +static unsigned int video_drop_vf_cnt; +MODULE_PARM_DESC(video_drop_vf_cnt, "\n video_drop_vf_cnt\n"); +module_param(video_drop_vf_cnt, uint, 0664); + +enum toggle_out_fl_frame_e { + OUT_FA_A_FRAME, + OUT_FA_BANK_FRAME, + OUT_FA_B_FRAME +}; + +static unsigned int video_3d_format; +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) +static unsigned int mvc_flag; +#endif +static unsigned int force_3d_scaler = 3; +static int mode_3d_changed; +static int last_mode_3d; +#endif + +#ifdef TV_REVERSE +bool reverse; +#endif + +const char video_dev_id[] = "amvideo-dev"; + +const char video_dev_id2[] = "amvideo-dev2"; + +int onwaitendframe; + +static u32 vpp_hold_line = 8; +static u32 stop_update; + +struct video_dev_s video_dev[2] = { + {0x1d00 - 0x1d00, 0x1a50 - 0x1a50}, + {0x1900 - 0x1d00, 0x1e00 - 0x1a50} +}; + +struct video_dev_s *cur_dev = &video_dev[0]; +struct video_dev_s *get_video_cur_dev(void) +{ + return cur_dev; +} +static int cur_dev_idx; + +#ifdef CONFIG_PM +struct video_pm_state_s { + int event; + u32 vpp_misc; + int mem_pd_vd1; + int mem_pd_vd2; + int mem_pd_di_post; +}; +#endif + +#define PTS_LOGGING +#define PTS_THROTTLE +/* #define PTS_TRACE_DEBUG */ +/* #define PTS_TRACE_START */ + +#ifdef PTS_TRACE_DEBUG +static int pts_trace_his[16]; +static u32 pts_his[16]; +static u32 scr_his[16]; +static int pts_trace_his_rd; +#endif + +#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) +static int pts_trace; +#endif + +#if defined(PTS_LOGGING) +#define PTS_32_PATTERN_DETECT_RANGE 10 +#define PTS_22_PATTERN_DETECT_RANGE 10 +#define PTS_41_PATTERN_DETECT_RANGE 2 +#define PTS_32_PATTERN_DURATION 3750 +#define PTS_22_PATTERN_DURATION 3000 + + +enum video_refresh_pattern { + PTS_32_PATTERN = 0, + PTS_22_PATTERN, + PTS_41_PATTERN, + PTS_MAX_NUM_PATTERNS +}; + +int n_patterns = PTS_MAX_NUM_PATTERNS; + +static int pts_pattern[3] = {0, 0, 0}; +static int pts_pattern_enter_cnt[3] = {0, 0, 0}; +static int pts_pattern_exit_cnt[3] = {0, 0, 0}; +static int pts_log_enable[3] = {0, 0, 0}; +static int pre_pts_trace; +static int pts_escape_vsync = -1; + +#define PTS_41_PATTERN_SINK_MAX 4 +static int pts_41_pattern_sink[PTS_41_PATTERN_SINK_MAX]; +static int pts_41_pattern_sink_index; +static int pts_pattern_detected = -1; +static bool pts_enforce_pulldown = true; +#endif + +static DEFINE_MUTEX(video_module_mutex); +static DEFINE_MUTEX(video_inuse_mutex); +static DEFINE_SPINLOCK(lock); +#if ENABLE_UPDATE_HDR_FROM_USER +static DEFINE_SPINLOCK(omx_hdr_lock); +#endif +static u32 frame_par_ready_to_set, frame_par_force_to_set; +static u32 vpts_remainder; +static int video_property_changed; +static u32 video_notify_flag; +static int enable_video_discontinue_report = 1; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER +static u32 video_scaler_mode; +static int content_top = 0, content_left = 0, content_w = 0, content_h; +static int scaler_pos_changed; +#endif + +#ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION +bool is_dolby_vision_enable(void) +{ + return 0; +} +bool is_dolby_vision_on(void) +{ + return 0; +} +bool is_dolby_vision_stb_mode(void) +{ + return 0; +} +#endif + +static struct amvideocap_req *capture_frame_req; +u32 get_video_angle(void) +{ + return glayer_info[0].angle; +} +EXPORT_SYMBOL(get_video_angle); + +/*for video related files only.*/ +void video_module_lock(void) +{ + mutex_lock(&video_module_mutex); +} +void video_module_unlock(void) +{ + mutex_unlock(&video_module_mutex); +} + +int video_property_notify(int flag) +{ + video_property_changed = flag; + return 0; +} + +#if defined(PTS_LOGGING) +static ssize_t pts_pattern_enter_cnt_read_file(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[20]; + ssize_t len; + + len = snprintf(buf, 20, "%d,%d,%d\n", pts_pattern_enter_cnt[0], + pts_pattern_enter_cnt[1], pts_pattern_enter_cnt[2]); + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t pts_pattern_exit_cnt_read_file(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[20]; + ssize_t len; + + len = snprintf(buf, 20, "%d,%d,%d\n", pts_pattern_exit_cnt[0], + pts_pattern_exit_cnt[1], pts_pattern_exit_cnt[2]); + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t pts_log_enable_read_file(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[20]; + ssize_t len; + + len = snprintf(buf, 20, "%d,%d,%d\n", pts_log_enable[0], + pts_log_enable[1], pts_log_enable[2]); + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t pts_log_enable_write_file(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[20]; + int ret; + + count = min_t(size_t, count, (sizeof(buf)-1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + buf[count] = 0; + /* pts_pattern_log_enable (3:2) (2:2) (4:1) */ + ret = sscanf(buf, "%d,%d,%d", &pts_log_enable[0], &pts_log_enable[1], + &pts_log_enable[2]); + if (ret != 3) { + pr_info("use echo 0/1,0/1,0/1 > /sys/kernel/debug/pts_log_enable\n"); + } else { + pr_info("pts_log_enable: %d,%d,%d\n", pts_log_enable[0], + pts_log_enable[1], pts_log_enable[2]); + } + return count; +} +static ssize_t pts_enforce_pulldown_read_file(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[16]; + ssize_t len; + + len = snprintf(buf, 16, "%d\n", pts_enforce_pulldown); + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t pts_enforce_pulldown_write_file(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + unsigned int write_val; + char buf[16]; + int ret; + + count = min_t(size_t, count, (sizeof(buf)-1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + buf[count] = 0; + ret = kstrtoint(buf, 0, &write_val); + if (ret != 0) + return -EINVAL; + pr_info("pts_enforce_pulldown: %d->%d\n", + pts_enforce_pulldown, write_val); + pts_enforce_pulldown = write_val; + return count; +} + +static const struct file_operations pts_pattern_enter_cnt_file_ops = { + .open = simple_open, + .read = pts_pattern_enter_cnt_read_file, +}; + +static const struct file_operations pts_pattern_exit_cnt_file_ops = { + .open = simple_open, + .read = pts_pattern_exit_cnt_read_file, +}; + +static const struct file_operations pts_log_enable_file_ops = { + .open = simple_open, + .read = pts_log_enable_read_file, + .write = pts_log_enable_write_file, +}; + +static const struct file_operations pts_enforce_pulldown_file_ops = { + .open = simple_open, + .read = pts_enforce_pulldown_read_file, + .write = pts_enforce_pulldown_write_file, +}; +#endif + +struct video_debugfs_files_s { + const char *name; + const umode_t mode; + const struct file_operations *fops; +}; + +static struct video_debugfs_files_s video_debugfs_files[] = { +#if defined(PTS_LOGGING) + {"pts_pattern_enter_cnt", S_IFREG | 0444, + &pts_pattern_enter_cnt_file_ops + }, + {"pts_pattern_exit_cnt", S_IFREG | 0444, + &pts_pattern_exit_cnt_file_ops + }, + {"pts_log_enable", S_IFREG | 0644, + &pts_log_enable_file_ops + }, + {"pts_enforce_pulldown", S_IFREG | 0644, + &pts_enforce_pulldown_file_ops + }, +#endif +}; + +static struct dentry *video_debugfs_root; +static void video_debugfs_init(void) +{ + struct dentry *ent; + int i; + + if (video_debugfs_root) + return; + video_debugfs_root = debugfs_create_dir("video", NULL); + if (!video_debugfs_root) + pr_err("can't create video debugfs dir\n"); + + for (i = 0; i < ARRAY_SIZE(video_debugfs_files); i++) { + ent = debugfs_create_file(video_debugfs_files[i].name, + video_debugfs_files[i].mode, + video_debugfs_root, NULL, + video_debugfs_files[i].fops); + if (!ent) + pr_info("debugfs create file %s failed\n", + video_debugfs_files[i].name); + } +} + +static void video_debugfs_exit(void) +{ + debugfs_remove(video_debugfs_root); +} + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER +int video_scaler_notify(int flag) +{ + video_scaler_mode = flag; + video_property_changed = 1; + return 0; +} + +u32 amvideo_get_scaler_para(int *x, int *y, int *w, int *h, u32 *ratio) +{ + *x = content_left; + *y = content_top; + *w = content_w; + *h = content_h; + /* *ratio = 100; */ + return video_scaler_mode; +} + +void amvideo_set_scaler_para(int x, int y, int w, int h, int flag) +{ + struct disp_info_s *layer = &glayer_info[0]; + + mutex_lock(&video_module_mutex); + if (w < 2) + w = 0; + if (h < 2) + h = 0; + if (flag) { + if ((content_left != x) || (content_top != y) + || (content_w != w) || (content_h != h)) + scaler_pos_changed = 1; + content_left = x; + content_top = y; + content_w = w; + content_h = h; + } else { + layer->layer_left = x; + layer->layer_top = y; + layer->layer_width = w; + layer->layer_height = h; + } + video_property_changed = 1; + mutex_unlock(&video_module_mutex); +} + +u32 amvideo_get_scaler_mode(void) +{ + return video_scaler_mode; +} +#endif + +bool to_notify_trick_wait; +/* display canvas */ +#define DISPLAY_CANVAS_BASE_INDEX 0x60 + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +static struct vframe_s *cur_rdma_buf; +/* + *void vsync_rdma_config(void); + *void vsync_rdma_config_pre(void); + *bool is_vsync_rdma_enable(void); + *void start_rdma(void); + *void enable_rdma_log(int flag); + */ +static int enable_rdma_log_count; + +bool rdma_enable_pre; + +u32 disp_canvas_index[2][6] = { + { + DISPLAY_CANVAS_BASE_INDEX, + DISPLAY_CANVAS_BASE_INDEX + 1, + DISPLAY_CANVAS_BASE_INDEX + 2, + DISPLAY_CANVAS_BASE_INDEX + 3, + DISPLAY_CANVAS_BASE_INDEX + 4, + DISPLAY_CANVAS_BASE_INDEX + 5, + }, + { + DISPLAY_CANVAS_BASE_INDEX2, + DISPLAY_CANVAS_BASE_INDEX2 + 1, + DISPLAY_CANVAS_BASE_INDEX2 + 2, + DISPLAY_CANVAS_BASE_INDEX2 + 3, + DISPLAY_CANVAS_BASE_INDEX2 + 4, + DISPLAY_CANVAS_BASE_INDEX2 + 5, + } +}; + +static u32 disp_canvas[2][2]; +static u32 rdma_canvas_id; +static u32 next_rdma_canvas_id = 1; + +#ifdef VIDEO_PIP +static u32 pip_rdma_canvas_id; +static u32 pip_next_rdma_canvas_id = 1; +static struct vframe_s *pip_rdma_buf; +static struct vframe_s *pipbuf_to_put; +#endif + +#define DISPBUF_TO_PUT_MAX 8 +static struct vframe_s *dispbuf_to_put[DISPBUF_TO_PUT_MAX]; +static int dispbuf_to_put_num; +#else +static u32 disp_canvas_index[6] = { + DISPLAY_CANVAS_BASE_INDEX, + DISPLAY_CANVAS_BASE_INDEX + 1, + DISPLAY_CANVAS_BASE_INDEX + 2, + DISPLAY_CANVAS_BASE_INDEX + 3, + DISPLAY_CANVAS_BASE_INDEX + 4, + DISPLAY_CANVAS_BASE_INDEX + 5, +}; + +static u32 disp_canvas[2]; +#endif + +static u32 post_canvas; + + +/* zoom information */ +static u32 zoom_start_x_lines; +static u32 zoom_end_x_lines; +static u32 zoom_start_y_lines; +static u32 zoom_end_y_lines; + +static u32 ori_start_x_lines; +static u32 ori_end_x_lines; +static u32 ori_start_y_lines; +static u32 ori_end_y_lines; + +static u32 zoom2_start_x_lines; +static u32 zoom2_end_x_lines; +static u32 zoom2_start_y_lines; +static u32 zoom2_end_y_lines; + +static u32 ori2_start_x_lines; +static u32 ori2_end_x_lines; +static u32 ori2_start_y_lines; +static u32 ori2_end_y_lines; + +/* black out policy */ +#if defined(CONFIG_JPEGLOGO) +static u32 blackout; +#else +static u32 blackout = 1; +#endif +static u32 force_blackout; +static u32 blackout_pip; + +/* disable video */ + +#ifdef VIDEO_PIP +static u32 pip_frame_count; +static u32 disable_videopip = VIDEO_DISABLE_FORNEXT; +static int pip_property_changed; +static u32 pip_frame_ready_to_set; +static u32 pip_global_output = 1; +static u32 pip_loop; +#endif + +static u32 disable_video = VIDEO_DISABLE_NONE; +static u32 video_enabled __nosavedata; +static u32 video2_enabled __nosavedata; +static u32 video_status_saved __nosavedata; +static u32 video2_status_saved __nosavedata; +static u32 hold_video; + +u32 get_video_enabled(void) +{ + return video_enabled; +} + +u32 get_videopip_enabled(void) +{ + return video2_enabled; +} + +/* show first frame*/ +static bool show_first_frame_nosync; +bool show_first_picture; +/* static bool first_frame=false; */ + +/* test screen*/ +static u32 test_screen; +/* rgb screen*/ +static u32 rgb_screen; + +/* video frame repeat count */ +static u32 frame_repeat_count; + +/* vout */ +static const struct vinfo_s *vinfo; + +/* config */ +static struct vframe_s *cur_dispbuf; +static struct vframe_s *cur_dispbuf2; +static bool need_disable_vd2; +static bool last_mvc_status; +void update_cur_dispbuf(void *buf) +{ + cur_dispbuf = buf; +} + +static struct vframe_s vf_local, vf_local2; +static u32 vsync_pts_inc; +static u32 vsync_pts_inc_scale; +static u32 vsync_pts_inc_scale_base = 1; +static u32 vsync_pts_inc_upint; +static u32 vsync_pts_inc_adj; +static u32 vsync_pts_125; +static u32 vsync_pts_112; +static u32 vsync_pts_101; +static u32 vsync_pts_100; +static u32 vsync_freerun; +/* extend this value to support both slow and fast playback + * 0,1: normal playback + * [2,1000]: speed/vsync_slow_factor + * >1000: speed*(vsync_slow_factor/1000000) + */ +static u32 vsync_slow_factor = 1; + +/* pts alignment */ +static bool vsync_pts_aligned; +static s32 vsync_pts_align; + +/* frame rate calculate */ +static u32 last_frame_count; +static u32 frame_count; +static u32 new_frame_count; +static u32 first_frame_toggled; +static u32 toggle_count; +static u32 last_frame_time; +static u32 timer_count; +static u32 vsync_count; +static u64 last_frame_duration; + +static struct vpp_frame_par_s *cur_frame_par, *next_frame_par; +static struct vpp_frame_par_s frame_parms[2]; + +/* vsync pass flag */ +static u32 wait_sync; + +/* is fffb or seeking*/ +static u32 video_seek_flag; + +#ifdef FIQ_VSYNC +static bridge_item_t vsync_fiq_bridge; +#endif + +/* trickmode i frame*/ +u32 trickmode_i; +EXPORT_SYMBOL(trickmode_i); + +/* trickmode ff/fb */ +u32 trickmode_fffb; +atomic_t trickmode_framedone = ATOMIC_INIT(0); +atomic_t video_sizechange = ATOMIC_INIT(0); +atomic_t video_unreg_flag = ATOMIC_INIT(0); +atomic_t video_inirq_flag = ATOMIC_INIT(0); +atomic_t video_pause_flag = ATOMIC_INIT(0); +int trickmode_duration; +int trickmode_duration_count; +u32 trickmode_vpts; +/* last_playback_filename */ +char file_name[512]; + +/* video freerun mode */ +#define FREERUN_NONE 0 /* no freerun mode */ +#define FREERUN_NODUR 1 /* freerun without duration */ +#define FREERUN_DUR 2 /* freerun with duration */ +static u32 freerun_mode; +static u32 slowsync_repeat_enable; +static bool dmc_adjust = true; +module_param_named(dmc_adjust, dmc_adjust, bool, 0644); +static u32 dmc_config_state; +static u32 last_toggle_count; +static u32 toggle_same_count; + +/* video_inuse */ +static u32 video_inuse; + +void set_freerun_mode(int mode) +{ + freerun_mode = mode; +} +EXPORT_SYMBOL(set_freerun_mode); + +void set_pts_realign(void) +{ + vsync_pts_aligned = false; +} +EXPORT_SYMBOL(set_pts_realign); + +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 }; + +/* wait queue for poll */ +static wait_queue_head_t amvideo_trick_wait; + +/* wait queue for poll */ +static wait_queue_head_t amvideo_sizechange_wait; + +/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ +#define VPU_DELAYWORK_VPU_CLK 1 +#define VPU_DELAYWORK_MEM_POWER_OFF_VD1 2 +#define VPU_DELAYWORK_MEM_POWER_OFF_VD2 4 +#define VPU_DELAYWORK_MEM_POWER_OFF_PROT 8 +#define VPU_VIDEO_LAYER1_CHANGED 16 +#define VPU_UPDATE_DOLBY_VISION 32 + +#define VPU_MEM_POWEROFF_DELAY 100 +static struct work_struct vpu_delay_work; +static int vpu_clk_level; +static DEFINE_SPINLOCK(delay_work_lock); +static int vpu_delay_work_flag; +static int vpu_mem_power_off_count; + +static u32 vpts_ref; +static u32 video_frame_repeat_count; +static u32 smooth_sync_enable; +static u32 hdmi_in_onvideo; +#ifdef CONFIG_AM_VIDEO2 +static int video_play_clone_rate = 60; +static int android_clone_rate = 30; +static int noneseamless_play_clone_rate = 5; +#endif + +#define CONFIG_AM_VOUT + +void safe_disable_videolayer(void) +{ +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + if (video_scaler_mode) + DisableVideoLayer_PREBELEND(); + else + DisableVideoLayer(); +#else + DisableVideoLayer(); +#endif +} + +#ifdef VIDEO_PIP +void safe_disable_videolayer2(void) +{ + DisableVideoLayer2(); +} +#endif +/*********************************************************/ +#ifdef VIDEO_PIP +static inline struct vframe_s *pip_vf_peek(void) +{ + if (pip_loop) + return cur_dispbuf; + return vf_peek(RECEIVERPIP_NAME); +} + +static inline struct vframe_s *pip_vf_get(void) +{ + struct vframe_s *vf = NULL; + + if (pip_loop) + return cur_dispbuf; + + vf = vf_get(RECEIVERPIP_NAME); + + if (vf) { + /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */ + atomic_set(&vf->use_cnt, 1); + } + return vf; + +} + +static inline void pip_vf_put(struct vframe_s *vf) +{ + struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP_NAME); + + if (pip_loop) + return; + + if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) { + vf_put(vf, RECEIVERPIP_NAME); + /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */ + } +} +#endif + +static inline struct vframe_s *video_vf_peek(void) +{ + struct vframe_s *vf = vf_peek(RECEIVER_NAME); + + if (hist_test_flag) { + if (cur_dispbuf != &hist_test_vf) + vf = &hist_test_vf; + else + vf = NULL; + } + + if (vf && vf->disp_pts && vf->disp_pts_us64) { + vf->pts = vf->disp_pts; + vf->pts_us64 = vf->disp_pts_us64; + vf->disp_pts = 0; + vf->disp_pts_us64 = 0; + } + return vf; +} + +static inline struct vframe_s *video_vf_get(void) +{ + struct vframe_s *vf = NULL; + int frame_width, frame_height; + + if (hist_test_flag) { + if (cur_dispbuf != &hist_test_vf) + vf = &hist_test_vf; + return vf; + } + + vf = vf_get(RECEIVER_NAME); + if (vf) { + if (vf->disp_pts && vf->disp_pts_us64) { + vf->pts = vf->disp_pts; + vf->pts_us64 = vf->disp_pts_us64; + vf->disp_pts = 0; + vf->disp_pts_us64 = 0; + } + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } + video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; + atomic_set(&vf->use_cnt, 1); + /*always to 1,for first get from vfm provider */ + if ((vf->type & VIDTYPE_MVC) && (framepacking_support) + &&(framepacking_width) && (framepacking_height)) { + vf->width = framepacking_width; + vf->height = framepacking_height; + } +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + /*can be moved to h264mvc.c */ + if ((vf->type & VIDTYPE_MVC) + && (process_3d_type & MODE_3D_ENABLE) && vf->trans_fmt) { + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + process_3d_type |= MODE_3D_MVC; + mvc_flag = 1; + } else { + process_3d_type &= (~MODE_3D_MVC); + mvc_flag = 0; + } + if (((process_3d_type & MODE_FORCE_3D_TO_2D_LR) + || (process_3d_type & MODE_FORCE_3D_LR) + || (process_3d_type & MODE_FORCE_3D_FA_LR)) + && (!(vf->type & VIDTYPE_MVC)) + && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { + vf->trans_fmt = TVIN_TFMT_3D_DET_LR; + vf->left_eye.start_x = 0; + vf->left_eye.start_y = 0; + vf->left_eye.width = frame_width / 2; + vf->left_eye.height = frame_height; + + vf->right_eye.start_x = frame_width / 2; + vf->right_eye.start_y = 0; + vf->right_eye.width = frame_width / 2; + vf->right_eye.height = frame_height; + } + if (((process_3d_type & MODE_FORCE_3D_TO_2D_TB) + || (process_3d_type & MODE_FORCE_3D_TB) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) + && (!(vf->type & VIDTYPE_MVC)) + && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { + vf->trans_fmt = TVIN_TFMT_3D_TB; + vf->left_eye.start_x = 0; + vf->left_eye.start_y = 0; + vf->left_eye.width = frame_width; + vf->left_eye.height = frame_height/2; + + vf->right_eye.start_x = 0; + vf->right_eye.start_y = frame_height/2; + vf->right_eye.width = frame_width; + vf->right_eye.height = frame_height/2; + } + receive_frame_count++; +#endif + } + return vf; + +} + +static int video_vf_get_states(struct vframe_states *states) +{ + int ret = -1; + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + ret = vf_get_states_by_name(RECEIVER_NAME, states); + spin_unlock_irqrestore(&lock, flags); + return ret; +} + +static inline void video_vf_put(struct vframe_s *vf) +{ + struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME); + + if (vf == &hist_test_vf) + return; + + if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) { + vf_put(vf, RECEIVER_NAME); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable()) + dolby_vision_vf_put(vf); +#endif + video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; + } +} + +int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index) +{ + if (cur_dispbuf == NULL) + return -1; + atomic_inc(&cur_dispbuf->use_cnt); + *canvas_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off); + *vf = cur_dispbuf; + return 0; +} +static void dump_vframe_status(const char *name) +{ + int ret = -1; + struct vframe_states states; + struct vframe_provider_s *vfp; + + vfp = vf_get_provider_by_name(name); + if (vfp && vfp->ops && vfp->ops->vf_states) + ret = vfp->ops->vf_states(&states, vfp->op_arg); + + if (ret == 0) { + ret += pr_info("%s_pool_size=%d\n", + name, states.vf_pool_size); + ret += pr_info("%s buf_free_num=%d\n", + name, states.buf_free_num); + ret += pr_info("%s buf_avail_num=%d\n", + name, states.buf_avail_num); + } else { + ret += pr_info("%s vframe no states\n", name); + } +} + +static void dump_vdin_reg(void) +{ + unsigned int reg001, reg002; + + reg001 = READ_VCBUS_REG(0x1204); + reg002 = READ_VCBUS_REG(0x1205); + pr_info("VDIN_LCNT_STATUS:0x%x,VDIN_COM_STATUS0:0x%x\n", + reg001, reg002); +} + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE +int ext_put_video_frame(struct vframe_s *vf) +{ + if (vf == &vf_local) + return 0; + video_vf_put(vf); + return 0; +} + +static int is_need_framepacking_output(void) +{ + int ret = 0; + + if ((framepacking_support) && + (cur_dispbuf) && (cur_dispbuf->type & VIDTYPE_MVC)) { + ret = 1; + } + return ret; +} + +int ext_register_end_frame_callback(struct amvideocap_req *req) +{ + mutex_lock(&video_module_mutex); + capture_frame_req = req; + mutex_unlock(&video_module_mutex); + return 0; +} +int ext_frame_capture_poll(int endflags) +{ + mutex_lock(&video_module_mutex); + if (capture_frame_req && capture_frame_req->callback) { + struct vframe_s *vf; + int index; + int ret; + struct amvideocap_req *req = capture_frame_req; + + ret = ext_get_cur_video_frame(&vf, &index); + if (!ret) { + req->callback(req->data, vf, index); + capture_frame_req = NULL; + } + } + mutex_unlock(&video_module_mutex); + return 0; +} +#endif + +static void update_layer_info(u8 layer_id) +{ + struct disp_info_s *layer; + + if (layer_id >= MAX_VD_LAYERS) + return; + + if (layer_id == 0) { + layer = &glayer_info[0]; + layer->reverse = reverse; + layer->proc_3d_type = process_3d_type; + } else if (layer_id == 1) { + layer = &glayer_info[1]; + layer->reverse = reverse; + layer->proc_3d_type = 0; + } +} + +static void vpp_settings_h(struct vpp_frame_par_s *framePtr) +{ + struct vppfilter_mode_s *vpp_filter = &framePtr->vpp_filter; + u32 r1, r2, r3; + + u32 x_lines; + + r1 = framePtr->VPP_hsc_linear_startp - framePtr->VPP_hsc_startp; + r2 = framePtr->VPP_hsc_linear_endp - framePtr->VPP_hsc_startp; + r3 = framePtr->VPP_hsc_endp - framePtr->VPP_hsc_startp; + + if ((framePtr->supscl_path == CORE0_PPS_CORE1) || + (framePtr->supscl_path == CORE1_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) + r3 >>= framePtr->supsc1_hori_ratio; + if ((framePtr->supscl_path == CORE0_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) + r3 >>= framePtr->supsc0_hori_ratio; + + x_lines = zoom_end_x_lines / (framePtr->hscale_skip_count + 1); + if (process_3d_type & MODE_3D_OUT_TB) { + /* vd1 and vd2 do pre blend */ + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((zoom_end_x_lines) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, + ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((zoom_end_x_lines) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) + << VPP_VD1_START_BIT) | + ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + } else if (process_3d_type & MODE_3D_OUT_LR) { + /* vd1 and vd2 do pre blend */ + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((x_lines >> 1) & + VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, + ((((x_lines + 1) >> 1) & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | ((x_lines & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) + << VPP_VD1_START_BIT) | + ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + } else{ + if (!legacy_vpp) { + x_lines = (zoom_end_x_lines - + zoom_start_x_lines + 1) + / (framePtr->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG( + VPP_PREBLEND_VD1_H_START_END, + ((0 & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((x_lines - 1) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_VD1_H_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) + << VPP_VD1_START_BIT) | + ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_hd_start_lines_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_START_BIT) | + ((framePtr->VPP_hd_end_lines_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + } + } + + VSYNC_WR_MPEG_REG(VPP_HSC_REGION12_STARTP + + cur_dev->vpp_off, + (0 << VPP_REGION1_BIT) | + ((r1 & VPP_REGION_MASK) << VPP_REGION2_BIT)); + + VSYNC_WR_MPEG_REG(VPP_HSC_REGION34_STARTP + cur_dev->vpp_off, + ((r2 & VPP_REGION_MASK) << VPP_REGION3_BIT) | + ((r3 & VPP_REGION_MASK) << VPP_REGION4_BIT)); + VSYNC_WR_MPEG_REG(VPP_HSC_REGION4_ENDP + cur_dev->vpp_off, r3); + + VSYNC_WR_MPEG_REG(VPP_HSC_START_PHASE_STEP + cur_dev->vpp_off, + vpp_filter->vpp_hf_start_phase_step); + + VSYNC_WR_MPEG_REG(VPP_HSC_REGION1_PHASE_SLOPE + cur_dev->vpp_off, + vpp_filter->vpp_hf_start_phase_slope); + + VSYNC_WR_MPEG_REG(VPP_HSC_REGION3_PHASE_SLOPE + cur_dev->vpp_off, + vpp_filter->vpp_hf_end_phase_slope); + + VSYNC_WR_MPEG_REG(VPP_LINE_IN_LENGTH + cur_dev->vpp_off, + framePtr->VPP_line_in_length_); +} + +static void vd2_settings_h(struct vframe_s *vf) +{ + u32 VPP_hd_start_lines_; + u32 VPP_hd_end_lines_; + + if (vf) { + VPP_hd_start_lines_ = 0; + VPP_hd_end_lines_ = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + + cur_dev->vpp_off, + ((VPP_hd_start_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + ((VPP_hd_end_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } +} + +static void vpp_settings_v(struct vpp_frame_par_s *framePtr) +{ + struct vppfilter_mode_s *vpp_filter = &framePtr->vpp_filter; + u32 r, afbc_enble_flag; + u32 y_lines; + u32 v_phase; + u32 v_skip_flag = 0; + int x, y, w, h; + struct disp_info_s *layer = &glayer_info[0]; + + r = framePtr->VPP_vsc_endp - framePtr->VPP_vsc_startp; + afbc_enble_flag = 0; + if (is_meson_gxbb_cpu()) + afbc_enble_flag = READ_VCBUS_REG(AFBC_ENABLE) & 0x100; + if ((vpp_filter->vpp_vsc_start_phase_step > 0x1000000) + && afbc_enble_flag) + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END + + cur_dev->vpp_off, ((framePtr->VPP_vsc_startp & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) + | (((framePtr->VPP_vsc_endp + 1) & VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + else { + afbc_enble_flag = READ_VCBUS_REG(AFBC_ENABLE) & 0x100; + v_phase = vpp_filter->vpp_vsc_start_phase_step; + + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; + if (v_phase * (framePtr->vscale_skip_count + 1) > 0x1000000) { + if ((afbc_enble_flag) && (y < 0)) { + if ((framePtr->VPP_vsc_endp < 0x250) || + (framePtr->VPP_vsc_endp < + framePtr->VPP_post_blend_vd_v_end_/2)) { + if (framePtr->VPP_vsc_endp > 0x6) + v_skip_flag = 1; + } + } + } + if (v_skip_flag == 1) { + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END + + cur_dev->vpp_off, ((framePtr->VPP_vsc_startp & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) + | (((framePtr->VPP_vsc_endp - 6) & VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + } else { + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END + + cur_dev->vpp_off, ((framePtr->VPP_vsc_startp & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) + | ((framePtr->VPP_vsc_endp & VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + } + } + + y_lines = zoom_end_y_lines / (framePtr->vscale_skip_count + 1); + if (process_3d_type & MODE_3D_OUT_TB) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, + ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((y_lines >> 1) & + VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_V_START_END, + ((((y_lines + 1) >> 1) & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | + ((y_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + } else if (process_3d_type & MODE_3D_OUT_LR) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, + ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | ((zoom_end_y_lines & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END, + ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | ((zoom_end_y_lines & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } else { + if ((framePtr->VPP_post_blend_vd_v_end_ - + framePtr->VPP_post_blend_vd_v_start_ + 1) > + VPP_PREBLEND_VD_V_END_LIMIT) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_post_blend_vd_v_start_ + & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | + ((framePtr->VPP_post_blend_vd_v_end_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + } else { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + cur_dev->vpp_off, + ((0 & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | + (((VPP_PREBLEND_VD_V_END_LIMIT - 1) & + VPP_VD_SIZE_MASK) << + VPP_VD1_END_BIT)); + } +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((framePtr->VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } + if (is_need_framepacking_output()) { + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + (((((framePtr->VPP_vd_end_lines_ - + framepacking_blank + 1) / 2) + framepacking_blank) & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((framePtr->VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } + } + VSYNC_WR_MPEG_REG(VPP_VSC_REGION12_STARTP + cur_dev->vpp_off, 0); + VSYNC_WR_MPEG_REG(VPP_VSC_REGION34_STARTP + cur_dev->vpp_off, + ((r & VPP_REGION_MASK) << VPP_REGION3_BIT) | + ((r & VPP_REGION_MASK) << VPP_REGION4_BIT)); + + if ((framePtr->supscl_path == CORE0_PPS_CORE1) || + (framePtr->supscl_path == CORE1_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) + r >>= framePtr->supsc1_vert_ratio; + if ((framePtr->supscl_path == CORE0_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) + r >>= framePtr->supsc0_vert_ratio; + + VSYNC_WR_MPEG_REG(VPP_VSC_REGION4_ENDP + cur_dev->vpp_off, r); + + VSYNC_WR_MPEG_REG(VPP_VSC_START_PHASE_STEP + cur_dev->vpp_off, + vpp_filter->vpp_vsc_start_phase_step); +} + +static void vd2_settings_v(struct vframe_s *vf) +{ + u32 VPP_vd_start_lines_; + u32 VPP_vd_end_lines_; + + if (vf) { + VPP_vd_start_lines_ = 0; + VPP_vd_end_lines_ = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + ((VPP_vd_start_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } +} + +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) +static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, + u32 *le, u32 *rs, u32 *re) +{ + u32 crop_sx, crop_ex, crop_sy, crop_ey; + int frame_width, frame_height; + struct disp_info_s *layer = &glayer_info[0]; + + if (!vf) + return; + + crop_sy = layer->crop_top; + crop_sx = layer->crop_left; + crop_ey = layer->crop_bottom; + crop_ex = layer->crop_right; + + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } + + switch (vpp_3d_mode) { + case VPP_3D_MODE_LR: + /*half width,double height */ + *ls = zoom_start_x_lines; + *le = zoom_end_x_lines; + *rs = *ls + (frame_width >> 1); + *re = *le + (frame_width >> 1); + if (process_3d_type & MODE_3D_OUT_LR) { + *ls = zoom_start_x_lines; + *le = zoom_end_x_lines >> 1; + *rs = *ls + (frame_width >> 1); + *re = *le + (frame_width >> 1); + } + break; + case VPP_3D_MODE_TB: + case VPP_3D_MODE_LA: + case VPP_3D_MODE_FA: + default: + 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 = zoom_start_x_lines; + *le = zoom_end_x_lines >> 1; + *rs = *ls; + *re = *le; + /* *rs = *ls + (vf->width); */ + /* *re = *le + (vf->width); */ + } else { + *ls = *rs = zoom_start_x_lines; + *le = *re = zoom_end_x_lines; + } + break; + } +} + +static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, + u32 *le, u32 *rs, u32 *re) +{ + u32 crop_sx, crop_ex, crop_sy, crop_ey, height; + int frame_width, frame_height; + struct disp_info_s *layer = &glayer_info[0]; + + if (!vf) + return; + + crop_sy = layer->crop_top; + crop_sx = layer->crop_left; + crop_ey = layer->crop_bottom; + crop_ex = layer->crop_right; + + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } + + if (vf->type & VIDTYPE_INTERLACE) + height = frame_height >> 1; + else + height = frame_height; + + switch (vpp_3d_mode) { + case VPP_3D_MODE_TB: + if (vf->trans_fmt == TVIN_TFMT_3D_FP) { + if (vf->type & VIDTYPE_INTERLACE) { + /*if input is interlace vertical*/ + /*crop will be reduce by half */ + *ls = + (vf->left_eye.start_y + + (crop_sy >> 1)) >> 1; + *le = + ((vf->left_eye.start_y + + vf->left_eye.height - + (crop_ey >> 1)) >> 1) - 1; + *rs = + (vf->right_eye.start_y + + (crop_sy >> 1)) >> 1; + *re = + ((vf->right_eye.start_y + + vf->left_eye.height - + (crop_ey >> 1)) >> 1) - 1; + } else { + *ls = vf->left_eye.start_y + (crop_sy >> 1); + *le = vf->left_eye.start_y + + vf->left_eye.height - + (crop_ey >> 1) - 1; + *rs = vf->right_eye.start_y + (crop_sy >> 1); + *re = + vf->right_eye.start_y + + vf->left_eye.height - (crop_ey >> 1) - 1; + } + } else { + if ((vf->type & VIDTYPE_VIU_FIELD) + && (vf->type & VIDTYPE_INTERLACE)) { + *ls = zoom_start_y_lines >> 1; + *le = zoom_end_y_lines >> 1; + *rs = *ls + (height >> 1); + *re = *le + (height >> 1); + + } else if (vf->type & VIDTYPE_INTERLACE) { + *ls = zoom_start_y_lines >> 1; + *le = zoom_end_y_lines >> 1; + *rs = *ls + height; + *re = *le + height; + + } else { + /* same width,same height */ + *ls = zoom_start_y_lines >> 1; + *le = zoom_end_y_lines >> 1; + *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 = zoom_start_y_lines; + *le = zoom_end_y_lines; + *rs = zoom_start_y_lines + (height >> 1); + *re = zoom_end_y_lines + (height >> 1); + } + } + break; + case VPP_3D_MODE_LR: + /* half width,double height */ + *ls = *rs = zoom_start_y_lines >> 1; + *le = *re = zoom_end_y_lines >> 1; + if ((process_3d_type & MODE_3D_TO_2D_MASK) + || (process_3d_type & MODE_3D_OUT_LR)) { + /*half width ,same height */ + *ls = *rs = zoom_start_y_lines; + *le = *re = zoom_end_y_lines; + } + break; + case 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 = *rs = zoom_start_y_lines; + *le = *re = zoom_end_y_lines; + } else { + *ls = *rs = (zoom_start_y_lines + crop_sy) >> 1; + *le = *re = (zoom_end_y_lines + crop_ey) >> 1; + } + break; + case VPP_3D_MODE_LA: + *ls = *rs = zoom_start_y_lines; + if ((process_3d_type & MODE_3D_LR_SWITCH) + || (process_3d_type & MODE_3D_TO_2D_R)) + *ls = *rs = zoom_start_y_lines + 1; + if (process_3d_type & MODE_3D_TO_2D_L) + *ls = *rs = zoom_start_y_lines; + *le = *re = zoom_end_y_lines; + if ((process_3d_type & MODE_3D_OUT_FA_MASK) + || (process_3d_type & MODE_3D_OUT_TB) + || (process_3d_type & MODE_3D_OUT_LR)) { + *rs = zoom_start_y_lines + 1; + *ls = zoom_start_y_lines; + /* *le = zoom_end_y_lines; */ + /* *re = zoom_end_y_lines; */ + } + break; + default: + *ls = *rs = zoom_start_y_lines; + *le = *re = zoom_end_y_lines; + break; + } +} + +#endif +static void zoom_display_horz(struct vframe_s *vf, int hscale) +{ + u32 ls = 0, le = 0, rs = 0, re = 0; +#ifdef TV_REVERSE + int content_w, content_l, content_r; +#endif +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + if (process_3d_type & MODE_3D_ENABLE) { + zoom_get_horz_pos(vf, cur_frame_par->vpp_3d_mode, &ls, + &le, &rs, &re); + } else { + ls = rs = zoom_start_x_lines; + le = re = zoom_end_x_lines; + } +#else + ls = rs = zoom_start_x_lines; + le = re = zoom_end_x_lines; +#endif + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_X0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_X0 + cur_dev->viu_off, + (ls / 2 << VDIF_PIC_START_BIT) | + (le / 2 << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_X1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_X1 + cur_dev->viu_off, + (rs / 2 << VDIF_PIC_START_BIT) | + (re / 2 << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG(VIU_VD1_FMT_W + cur_dev->viu_off, + (((zoom_end_x_lines - zoom_start_x_lines + + 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | + (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + int l_aligned; + int r_aligned; + int h_skip = cur_frame_par->hscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && (vf->type & VIDTYPE_VIU_444)) + c_skip = 1; + + if ((zoom_start_x_lines > 0) || + (zoom_end_x_lines < ori_end_x_lines)) { + l_aligned = round_down(ori_start_x_lines, 32); + r_aligned = round_up(ori_end_x_lines + 1, 32); + } else { + l_aligned = round_down(zoom_start_x_lines, 32); + r_aligned = round_up(zoom_end_x_lines + 1, 32); + } + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_W, + (((r_aligned - l_aligned) / h_skip) << 16) | + ((r_aligned / c_skip - l_aligned / c_skip) / h_skip)); + + VSYNC_WR_MPEG_REG(AFBC_MIF_HOR_SCOPE, + ((l_aligned / 32) << 16) | + ((r_aligned / 32) - 1)); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT, + (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) + & 0xffff) | + (((r_aligned - l_aligned) / h_skip) << 16)); + } +#ifdef TV_REVERSE + if (reverse) { + content_w = zoom_end_x_lines - zoom_start_x_lines + 1; + content_l = (r_aligned - zoom_end_x_lines - 1); + content_r = content_l + content_w - 1; + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + (((content_l << 16)) | content_r) / h_skip); + } else +#endif + { + if (((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_LR)) + && (cur_frame_par->vpp_3d_mode == 1)) { + /* do nothing*/ + } else { + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + (((zoom_start_x_lines - l_aligned) << 16) | + (zoom_end_x_lines - l_aligned)) / h_skip); + } + } + VSYNC_WR_MPEG_REG(AFBC_SIZE_IN, + (VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) & 0xffff) | + ((r_aligned - l_aligned) << 16)); + } + +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X0 + cur_dev->viu_off, + (ls / 2 << VDIF_PIC_START_BIT) | + (le / 2 << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X1 + cur_dev->viu_off, + (rs / 2 << VDIF_PIC_START_BIT) | + (re / 2 << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_W + cur_dev->viu_off, + (((zoom_end_x_lines - zoom_start_x_lines + + 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | + (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); + } +} + +static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) +{ + u32 ls, le, rs, re; +#ifdef TV_REVERSE + int content_w, content_l, content_r; +#endif + ls = rs = zoom2_start_x_lines; + le = re = zoom2_end_x_lines; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + int l_aligned; + int r_aligned; + int h_skip = hscale + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && (vf->type & VIDTYPE_VIU_444)) + c_skip = 1; + + if ((zoom2_start_x_lines > 0) || + (zoom2_end_x_lines < ori2_end_x_lines)) { + l_aligned = round_down(ori2_start_x_lines, 32); + r_aligned = round_up(ori2_end_x_lines + 1, 32); + } else { + l_aligned = round_down(zoom2_start_x_lines, 32); + r_aligned = round_up(zoom2_end_x_lines + 1, 32); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_W, + (((r_aligned - l_aligned) / h_skip) << 16) | + ((r_aligned / c_skip - l_aligned / c_skip) / h_skip)); + + VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_HOR_SCOPE, + ((l_aligned / 32) << 16) | + ((r_aligned / 32) - 1)); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT, + (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT) + & 0xffff) | + (((r_aligned - l_aligned) / h_skip) << 16)); + } +#ifdef TV_REVERSE + if (reverse) { + content_w = zoom2_end_x_lines - zoom2_start_x_lines + 1; + content_l = (r_aligned - zoom2_end_x_lines - 1) + + (zoom2_start_x_lines - l_aligned); + content_r = content_l + content_w - 1; + VSYNC_WR_MPEG_REG(VD2_AFBC_PIXEL_HOR_SCOPE, + (content_l << 16) | content_r); + } else +#endif + { + VSYNC_WR_MPEG_REG(VD2_AFBC_PIXEL_HOR_SCOPE, + ((zoom2_start_x_lines - l_aligned) << 16) | + (zoom2_end_x_lines - l_aligned)); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_IN, + (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN) & 0xffff) | + ((r_aligned - l_aligned) << 16)); + } + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X0 + cur_dev->viu_off, + (ls / 2 << VDIF_PIC_START_BIT) | + (le / 2 << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X1 + cur_dev->viu_off, + (rs / 2 << VDIF_PIC_START_BIT) | + (re / 2 << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_W + cur_dev->viu_off, + (((le - ls + 1) >> hscale) + << VD1_FMT_LUMA_WIDTH_BIT) | + (((le / 2 - ls / 2 + 1) >> hscale) + << VD1_FMT_CHROMA_WIDTH_BIT)); +} + +static void zoom_display_vert(struct vframe_s *vf) +{ + + u32 ls = 0, le = 0, rs = 0, re = 0; + + if (process_3d_type & MODE_3D_ENABLE) { + #if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + zoom_get_vert_pos(vf, + cur_frame_par->vpp_3d_mode, &ls, + &le, &rs, &re); + #endif + } else { + ls = rs = zoom_start_y_lines; + le = re = zoom_end_y_lines; + } + + if ((vf) && (vf->type & VIDTYPE_MVC)) { + if (is_need_framepacking_output()) { + VSYNC_WR_MPEG_REG( + VD1_IF0_LUMA_Y0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD1_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((ls / 2) << VDIF_PIC_START_BIT) | + ((le / 2) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_Y0 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((rs / 2) << VDIF_PIC_START_BIT) | + ((re / 2) << VDIF_PIC_END_BIT)); + } else { + VSYNC_WR_MPEG_REG( + VD1_IF0_LUMA_Y0 + cur_dev->viu_off, + (ls * 2 << VDIF_PIC_START_BIT) | + ((le * 2 - 1) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD1_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((ls) << VDIF_PIC_START_BIT) | + ((le - 1) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_Y0 + cur_dev->viu_off, + (ls * 2 << VDIF_PIC_START_BIT) | + ((le * 2 - 1) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((ls) << VDIF_PIC_START_BIT) | + ((le - 1) << VDIF_PIC_END_BIT)); + } + } else { + VSYNC_WR_MPEG_REG( + VD1_IF0_LUMA_Y0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD1_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((ls / 2) << VDIF_PIC_START_BIT) | + ((le / 2) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD1_IF0_LUMA_Y1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD1_IF0_CHROMA_Y1 + cur_dev->viu_off, + ((rs / 2) << VDIF_PIC_START_BIT) | + ((re / 2) << VDIF_PIC_END_BIT)); + +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_Y0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((ls / 2) << VDIF_PIC_START_BIT) | + ((le / 2) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_Y1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_Y1 + cur_dev->viu_off, + ((rs / 2) << VDIF_PIC_START_BIT) | + ((re / 2) << VDIF_PIC_END_BIT)); + } + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + int t_aligned; + int b_aligned; + int ori_t_aligned; + int ori_b_aligned; + int v_skip = cur_frame_par->vscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && ((vf->type & VIDTYPE_VIU_444) + || (vf->type & VIDTYPE_VIU_422))) + c_skip = 1; + + t_aligned = round_down(zoom_start_y_lines, 4); + b_aligned = round_up(zoom_end_y_lines + 1, 4); + + ori_t_aligned = round_down(ori_start_y_lines, 4); + ori_b_aligned = round_up(ori_end_y_lines + 1, 4); + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_H, + (b_aligned - t_aligned) / c_skip / v_skip); + + if (((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) + && (cur_frame_par->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(AFBC_MIF_VER_SCOPE, + (((ori_t_aligned / 4) + block_h) << 16) | + ((ori_b_aligned / 4) - 1)); + } else { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((ori_t_aligned / 4) << 16) | + ((ori_t_aligned / 4) + block_h - 1)); + } + } else { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((t_aligned / 4) << 16) | + ((b_aligned / 4) - 1)); + } + VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE, + ((zoom_start_y_lines - t_aligned) << 16) | + (zoom_end_y_lines - t_aligned)); + /* afbc pixel vertical output region must be + * [0, zoom_end_y_lines - zoom_start_y_lines] + */ + VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE, + (zoom_end_y_lines - zoom_start_y_lines)); + + VSYNC_WR_MPEG_REG(AFBC_SIZE_IN, + (VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) + & 0xffff0000) | + (ori_b_aligned - ori_t_aligned)); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT, + (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) & + 0xffff0000) | + ((b_aligned - t_aligned) / v_skip)); + } + } +} + +static void vd2_zoom_display_vert(struct vframe_s *vf, int vscale) +{ + + u32 ls, le, rs, re; + + ls = rs = zoom2_start_y_lines; + le = re = zoom2_end_y_lines; + + /* vd2 */ + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_Y0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_Y0 + cur_dev->viu_off, + ((ls / 2) << VDIF_PIC_START_BIT) | + ((le / 2) << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_Y1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_Y1 + cur_dev->viu_off, + ((rs / 2) << VDIF_PIC_START_BIT) | + ((re / 2) << VDIF_PIC_END_BIT)); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + int t_aligned; + int b_aligned; + int ori_t_aligned; + int ori_b_aligned; + int v_skip = vscale + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && ((vf->type & VIDTYPE_VIU_444) + || (vf->type & VIDTYPE_VIU_422))) + c_skip = 1; + + t_aligned = round_down(zoom2_start_y_lines, 4); + b_aligned = round_up(zoom2_end_y_lines + 1, 4); + + ori_t_aligned = round_down(ori2_start_y_lines, 4); + ori_b_aligned = round_up(ori2_end_y_lines + 1, 4); + + /* TODO: afbc setting only support 420 for now */ + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H, + (b_aligned - t_aligned) / c_skip / v_skip); + + VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE, + ((t_aligned / 4) << 16) | + ((b_aligned / 4) - 1)); + + VSYNC_WR_MPEG_REG(VD2_AFBC_PIXEL_VER_SCOPE, + ((zoom2_start_y_lines - t_aligned) << 16) | + (zoom2_end_y_lines - t_aligned)); + + VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_IN, + (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN) + & 0xffff0000) | + (ori_b_aligned - ori_t_aligned)); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT, + (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT) + & 0xffff0000) | + ((b_aligned - t_aligned) / v_skip)); + } + } +} + +#ifdef TV_3D_FUNCTION_OPEN +/* judge the out mode is 240:LBRBLRBR or 120:LRLRLR */ +static void judge_3d_fa_out_mode(void) +{ + if ((process_3d_type & MODE_3D_OUT_FA_MASK) + && pause_one_3d_fl_frame == 2) + toggle_3d_fa_frame = OUT_FA_B_FRAME; + else if ((process_3d_type & MODE_3D_OUT_FA_MASK) + && pause_one_3d_fl_frame == 1) + toggle_3d_fa_frame = OUT_FA_A_FRAME; + else if ((process_3d_type & MODE_3D_OUT_FA_MASK) + && pause_one_3d_fl_frame == 0) { + /* toggle_3d_fa_frame determine*/ + /*the out frame is L or R or blank */ + if ((process_3d_type & MODE_3D_OUT_FA_L_FIRST)) { + if ((vsync_count % 2) == 0) + toggle_3d_fa_frame = OUT_FA_A_FRAME; + else + toggle_3d_fa_frame = OUT_FA_B_FRAME; + } else if ((process_3d_type & MODE_3D_OUT_FA_R_FIRST)) { + if ((vsync_count % 2) == 0) + toggle_3d_fa_frame = OUT_FA_B_FRAME; + else + toggle_3d_fa_frame = OUT_FA_A_FRAME; + } else if ((process_3d_type & MODE_3D_OUT_FA_LB_FIRST)) { + if ((vsync_count % 4) == 0) + toggle_3d_fa_frame = OUT_FA_A_FRAME; + else if ((vsync_count % 4) == 2) + toggle_3d_fa_frame = OUT_FA_B_FRAME; + else + toggle_3d_fa_frame = OUT_FA_BANK_FRAME; + } else if ((process_3d_type & MODE_3D_OUT_FA_RB_FIRST)) { + if ((vsync_count % 4) == 0) + toggle_3d_fa_frame = OUT_FA_B_FRAME; + else if ((vsync_count % 4) == 2) + toggle_3d_fa_frame = OUT_FA_A_FRAME; + else + toggle_3d_fa_frame = OUT_FA_BANK_FRAME; + } + } else + toggle_3d_fa_frame = OUT_FA_A_FRAME; +} + +#endif + +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); +} + +#ifdef PTS_LOGGING +static void log_vsync_video_pattern(int pattern) +{ + int factor1 = 0, factor2 = 0, pattern_range = 0; + + if (pattern >= PTS_MAX_NUM_PATTERNS) + return; + + if (pattern == PTS_32_PATTERN) { + factor1 = 3; + factor2 = 2; + pattern_range = PTS_32_PATTERN_DETECT_RANGE; + } else if (pattern == PTS_22_PATTERN) { + factor1 = 2; + factor2 = 2; + pattern_range = PTS_22_PATTERN_DETECT_RANGE; + } else if (pattern == PTS_41_PATTERN) { + /* update 2111 mode detection */ + if (pts_trace == 2) { + if ((pts_41_pattern_sink[1] == 1) && + (pts_41_pattern_sink[2] == 1) && + (pts_41_pattern_sink[3] == 1) && + (pts_pattern[PTS_41_PATTERN] < + PTS_41_PATTERN_DETECT_RANGE)) { + pts_pattern[PTS_41_PATTERN]++; + if (pts_pattern[PTS_41_PATTERN] == + PTS_41_PATTERN_DETECT_RANGE) { + pts_pattern_enter_cnt[PTS_41_PATTERN]++; + pts_pattern_detected = pattern; + if (pts_log_enable[PTS_41_PATTERN]) + pr_info("video 4:1 mode detected\n"); + } + } + pts_41_pattern_sink[0] = 2; + pts_41_pattern_sink_index = 1; + } else if (pts_trace == 1) { + if ((pts_41_pattern_sink_index < + PTS_41_PATTERN_SINK_MAX) && + (pts_41_pattern_sink_index > 0)) { + pts_41_pattern_sink[pts_41_pattern_sink_index] + = 1; + pts_41_pattern_sink_index++; + } else if (pts_pattern[PTS_41_PATTERN] == + PTS_41_PATTERN_DETECT_RANGE) { + pts_pattern[PTS_41_PATTERN] = 0; + pts_41_pattern_sink_index = 0; + pts_pattern_exit_cnt[PTS_41_PATTERN]++; + memset(&pts_41_pattern_sink[0], 0, + PTS_41_PATTERN_SINK_MAX); + if (pts_log_enable[PTS_41_PATTERN]) + pr_info("video 4:1 mode broken\n"); + } else { + pts_pattern[PTS_41_PATTERN] = 0; + pts_41_pattern_sink_index = 0; + memset(&pts_41_pattern_sink[0], 0, + PTS_41_PATTERN_SINK_MAX); + } + } else if (pts_pattern[PTS_41_PATTERN] == + PTS_41_PATTERN_DETECT_RANGE) { + pts_pattern[PTS_41_PATTERN] = 0; + pts_41_pattern_sink_index = 0; + memset(&pts_41_pattern_sink[0], 0, + PTS_41_PATTERN_SINK_MAX); + pts_pattern_exit_cnt[PTS_41_PATTERN]++; + if (pts_log_enable[PTS_41_PATTERN]) + pr_info("video 4:1 mode broken\n"); + } else { + pts_pattern[PTS_41_PATTERN] = 0; + pts_41_pattern_sink_index = 0; + memset(&pts_41_pattern_sink[0], 0, + PTS_41_PATTERN_SINK_MAX); + } + return; + } + + + /* update 3:2 or 2:2 mode detection */ + if (((pre_pts_trace == factor1) && (pts_trace == factor2)) || + ((pre_pts_trace == factor2) && (pts_trace == factor1))) { + if (pts_pattern[pattern] < pattern_range) { + pts_pattern[pattern]++; + if (pts_pattern[pattern] == pattern_range) { + pts_pattern_enter_cnt[pattern]++; + pts_pattern_detected = pattern; + if (pts_log_enable[pattern]) + pr_info("video %d:%d mode detected\n", + factor1, factor2); + } + } + } else if (pts_pattern[pattern] == pattern_range) { + pts_pattern[pattern] = 0; + pts_pattern_exit_cnt[pattern]++; + if (pts_log_enable[pattern]) + pr_info("video %d:%d mode broken\n", factor1, factor2); + } else + pts_pattern[pattern] = 0; +} + +static void vsync_video_pattern(void) +{ + /* Check for 3:2*/ + log_vsync_video_pattern(PTS_32_PATTERN); + /* Check for 2:2*/ + log_vsync_video_pattern(PTS_22_PATTERN); + /* Check for 4:1*/ + log_vsync_video_pattern(PTS_41_PATTERN); +} +#endif + +static inline void vd1_path_select(bool afbc) +{ + u32 misc_off = cur_dev->vpp_off; + + 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 ? 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) */ + (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); + +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + return; + if ((DI_POST_REG_RD(DI_POST_CTRL) & 0x100) != 0) { + /* 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); + } +#endif + } else { +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + if ((DI_POST_REG_RD(DI_POST_CTRL) & 0x100) == 0) + /* mif sel */ +#endif + 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 inline void vd2_path_select(bool afbc) +{ + u32 misc_off = cur_dev->vpp_off; + + 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 ? 1 : 0) << 12) | + /* data sel: vd2 & afbc1 (not osd4) */ + (0 << 11) | + /* data sel: afbc1 */ + ((afbc ? 1 : 0) << 10) | + /* afbc1 to vd2 (not di) */ + (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); + } +} + +#ifdef VIDEO_PIP +s32 config_vd_pps( + u8 layer_id, + struct vpp_frame_par_s *cur_frame_par, + struct scaler_setting_s *setting, + const struct vinfo_s *info) +{ + struct vppfilter_mode_s *vpp_filter; + + if (!cur_frame_par || !info || !setting) + return -1; + + vpp_filter = &cur_frame_par->vpp_filter; + setting->frame_par = cur_frame_par; + setting->id = layer_id; + setting->misc_reg_offt = 0; + /* enable pps as default */ + setting->sc_top_enable = true; + setting->sc_h_enable = true; + setting->sc_v_enable = true; + + 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 + && !cur_frame_par->supsc0_enable + && !cur_frame_par->supsc1_enable + && bypass_pps) + setting->sc_top_enable = false; + + /* old chip: vd2 has no pps */ + if ((legacy_vpp || is_meson_tl1_cpu()) + && (setting->id != 0)) + setting->sc_top_enable = false; + + setting->vinfo_width = info->width; + setting->vinfo_height = info->height; + return 0; +} + +static inline 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; + + if (legacy_vpp || !setting + || !setting->frame_par + || is_meson_tl1_cpu()) + 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) { + sc_misc_val |= (((vpp_filter->vpp_pre_hsc_en & 1) + << VPP_SC_PREHORZ_EN_BIT) + | VPP_SC_HORZ_EN); + 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); + } + 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) { + if (vpp_filter->vpp_horz_coeff[1] & 0x8000) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_HORZ | VPP_COEF_9BIT); + } 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); + + 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); + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_VERT); + for (i = 0; i < vpp_filter->vpp_vert_coeff[1]; 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; + 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_); +} + +s32 config_vd_blend( + u8 layer_id, + struct vpp_frame_par_s *cur_frame_par, + struct vframe_s *vf, + u32 layer_alpha, + struct blend_setting_s *setting) +{ + /* u32 type = 0; */ + u32 vskip, hskip; + + if (!cur_frame_par || !setting || !vf) + return -1; + + setting->frame_par = cur_frame_par; + setting->id = layer_id; + setting->misc_reg_offt = 0; + + setting->layer_alpha = layer_alpha; + setting->preblend_h_start = 0; + setting->preblend_h_end = 4096; + 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->VPP_line_in_length_; + + /* old chip, vd2 has no scaler, so only can use mif setting */ + if ((setting->id != 0) && + (legacy_vpp || is_meson_tl1_cpu())) { + vskip = cur_frame_par->vscale_skip_count; + hskip = cur_frame_par->hscale_skip_count; + + 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->VPP_line_in_length_ >> hskip) - 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->VPP_pic_in_height_ >> vskip) - 1; + setting->postblend_h_size = + cur_frame_par->VPP_post_blend_h_size_; + } else { + 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; + setting->postblend_h_size = + cur_frame_par->VPP_post_blend_h_size_; + } + + if (!legacy_vpp) { + u32 temp_h = cur_frame_par->VPP_pic_in_height_; + + 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; + } + + return 0; +} + +static inline void vd2_vpp_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 inline void proc_vd2_vsc_phase_per_vsync( + struct vpp_frame_par_s *frame_par, + struct vframe_s *vf, + u32 vout_type) +{ + struct f2v_vphase_s *vphase; + u32 misc_off, vin_type; + struct vppfilter_mode_s *vpp_filter; + + if (legacy_vpp || is_meson_tl1_cpu() + || !frame_par || !vf) + return; + + vpp_filter = &frame_par->vpp_filter; + misc_off = 0; + vin_type = vf->type & VIDTYPE_TYPEMASK; + /* vertical phase */ + vphase = &frame_par->VPP_vf_ini_phase_ + [vpp_phase_table[vin_type] + [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 pip_toggle_frame(struct vframe_s *vf) +{ + u32 first_picture = 0; + bool force_toggle = false; + + if (vf == NULL) + return; + + ori2_start_x_lines = 0; + ori2_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + ori2_start_y_lines = 0; + ori2_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + + if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) + pr_info("%s()\n", __func__); + + if ((vf->width == 0) && (vf->height == 0)) { + amlog_level(LOG_LEVEL_ERROR, + "Video: invalid frame dimension\n"); + return; + } + if (cur_pipbuf + && (cur_pipbuf != &local_pip) + && (cur_pipbuf != vf)) { + pip_frame_count++; + if (pip_frame_count == 1) + first_picture = 1; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { + if (pip_rdma_buf == cur_pipbuf) + pipbuf_to_put = cur_pipbuf; + else + pip_vf_put(cur_pipbuf); + } else { + if (pipbuf_to_put) { + pip_vf_put( + pipbuf_to_put); + pipbuf_to_put = NULL; + } + pip_vf_put(cur_pipbuf); + } +#else + pip_vf_put(cur_pipbuf); +#endif + } else if (!cur_pipbuf + || (cur_pipbuf == &local_pip)) + first_picture = 1; + + /* switch buffer */ + if (vf->type & VIDTYPE_COMPRESS) { + VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR, + vf->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR, + vf->compBodyAddr>>4); + } + if (vf->canvas0Addr != 0) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (vf->canvas0Addr != (u32)-1) { + canvas_copy(vf->canvas0Addr & 0xff, + disp_canvas_index[pip_rdma_canvas_id][3]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[pip_rdma_canvas_id][4]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[pip_rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas0_config[0], + vf->plane_num, + &disp_canvas_index[pip_rdma_canvas_id][3]); + } + + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[pip_rdma_canvas_id][1]); + + pip_next_rdma_canvas_id = pip_rdma_canvas_id ? 0 : 1; +#endif + } + + if (cur_pipbuf && + (cur_pipbuf->ratio_control & + DISP_RATIO_ADAPTED_PICMODE)) { + if (vf && (cur_pipbuf->ratio_control + == vf->ratio_control) + && memcmp(&cur_pipbuf->pic_mode, + &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + else if (memcmp(&cur_pipbuf->pic_mode, + &gPic_info[1], + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + } + + if (pip_property_changed) { + force_toggle = true; + pip_property_changed = 0; + } + if (cur_pipbuf != vf) + vf->type_backup = vf->type; + + /* enable new config on the new frames */ + if (first_picture || force_toggle || + (cur_pipbuf && + ((cur_pipbuf->bufWidth != vf->bufWidth) || + (cur_pipbuf->width != vf->width) || + (cur_pipbuf->height != vf->height) || + (cur_pipbuf->bitdepth != vf->bitdepth) || + #if defined(CONFIG_AMLOGIC_MEDIA_TVIN) + (cur_pipbuf->trans_fmt != vf->trans_fmt) || + #endif + (cur_pipbuf->ratio_control != vf->ratio_control) || + ((cur_pipbuf->type_backup & VIDTYPE_INTERLACE) != + (vf->type_backup & VIDTYPE_INTERLACE)) || + (cur_pipbuf->type != vf->type)))) { + int iret; + + /* apply new vpp settings */ + nextpip_frame_par = + (&pip_frame_parms[0] == nextpip_frame_par) ? + &pip_frame_parms[1] : &pip_frame_parms[0]; + + update_layer_info(1); + iret = vpp_set_filters( + &glayer_info[1], vf, + nextpip_frame_par, vinfo, + true, 1); + + memcpy(&gPic_info[1], &vf->pic_mode, + sizeof(struct vframe_pic_mode_s)); + + if (iret == VppFilter_Success_and_Changed) + pip_property_changed = 1; + + pip_frame_ready_to_set = 1; + } + + if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && + (!pip_property_changed || (vf != cur_pipbuf))) { + if (disable_videopip == VIDEO_DISABLE_FORNEXT) { + EnableVideoLayer2(); + disable_videopip = VIDEO_DISABLE_NONE; + } + if (first_picture && + (disable_videopip != + VIDEO_DISABLE_NORMAL)) { + EnableVideoLayer2(); + } + } + cur_pipbuf = vf; + if (first_picture) + pip_frame_ready_to_set = 1; + if (cur_pipbuf != &local_pip) + video_pip_keeper_new_frame_notify(); +} + +static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) +{ + u32 r; + u32 vphase, vini_phase; + 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; + u8 burst_len = 1; + + if (!vf || !frame_par) { + pr_err("%s vf is NULL\n", __func__); + return; + } + + type = vf->type; + pr_debug("%s %p, type:0x%x\n", __func__, 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; + +#ifdef TV_REVERSE + if (reverse) + r |= (1<<26) | (1<<27); +#endif + 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_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_ENABLE, r); + + r = 0x100; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + VSYNC_WR_MPEG_REG(VD2_AFBC_DEC_DEF_COLOR, + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ + r = HFORMATTER_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, 0); + } + + vd2_path_select(true); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + + cur_dev->viu_off, 0); + return; + } + + if ((vf->bitdepth & BITDEPTH_Y10) && + (!frame_par->nocomp)) { + if (vf->type & VIDTYPE_VIU_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(false); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (bit_mode & 0x3), 8, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG3 + cur_dev->viu_off, + (bit_mode&0x3), 8, 2); + } + if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1)) + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + if (type & VIDTYPE_VIU_NV21) + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 1, 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 0, 0, 1); + + 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 (debug_flag & 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) + r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; + + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, r); + +#ifdef TV_REVERSE + if (reverse) { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0xf, 2, 4); + } else { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0, 2, 4); + } +#endif + + /* chroma formatter */ + if (type & VIDTYPE_VIU_444) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_1_1); + } else if (type & VIDTYPE_VIU_FIELD) { + vini_phase = 0xc << VFORMATTER_INIPHASE_BIT; + vphase = ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT; + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && + (vf->height >= 2160) && + (type & VIDTYPE_VIU_422)) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } + + if (is_meson_txlx_cpu() + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + 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 (type & VIDTYPE_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_IF0_RPT_LOOP + cur_dev->viu_off, + (loop << VDIF_CHROMA_LOOP1_BIT) | + (loop << VDIF_LUMA_LOOP1_BIT) | + (loop << VDIF_CHROMA_LOOP0_BIT) | + (loop << VDIF_LUMA_LOOP0_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); +} +#endif + +/* for sdr/hdr/single dv switch with dual dv */ +static u32 last_el_status; +/* for dual dv switch with different el size */ +static u32 last_el_w; +bool has_enhanced_layer(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + + if (!vf) + return 0; + if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) + return 0; + if (!is_dolby_vision_on()) + return 0; + + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + return req.dv_enhance_exist; +} +u32 property_changed_true; + +static u64 func_div(u64 number, u32 divid) +{ + u64 tmp = number; + + do_div(tmp, divid); + return tmp; +} + +static void vsync_toggle_frame(struct vframe_s *vf, int line) +{ + static u32 last_pts; + u32 diff_pts; + u32 first_picture = 0; + unsigned long flags = 0; + bool vf_with_el = false; + bool force_toggle = false; + long long *clk_array; + bool is_mvc = false; + + ATRACE_COUNTER(__func__, line); + if (vf == NULL) + return; + ATRACE_COUNTER("vsync_toggle_frame_pts", vf->pts); + + diff_pts = vf->pts - last_pts; + if (last_pts && diff_pts < 90000) + ATRACE_COUNTER("vsync_toggle_frame_inc", diff_pts); + else + ATRACE_COUNTER("vsync_toggle_frame_inc", 0); /* discontinue */ + + last_pts = vf->pts; + + frame_count++; + toggle_count++; + + if (vf->type & VIDTYPE_MVC) + is_mvc = true; + + if (is_dolby_vision_enable()) + vf_with_el = has_enhanced_layer(vf); + +#ifdef PTS_TRACE_DEBUG +#ifdef PTS_TRACE_START + if (pts_trace_his_rd < 16) { +#endif + pts_trace_his[pts_trace_his_rd] = pts_trace; + pts_his[pts_trace_his_rd] = vf->pts; + scr_his[pts_trace_his_rd] = timestamp_pcrscr_get(); + pts_trace_his_rd++; + if (pts_trace_his_rd >= 16) + pts_trace_his_rd = 0; +#ifdef PTS_TRACE_START + } +#endif +#endif + +#ifdef PTS_LOGGING + if (pts_escape_vsync == 1) { + pts_trace++; + pts_escape_vsync = 0; + } + vsync_video_pattern(); + pre_pts_trace = pts_trace; +#endif + +#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) + pts_trace = 0; +#endif + + ori_start_x_lines = 0; + ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + ori_start_y_lines = 0; + ori_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) { + u32 pcr = timestamp_pcrscr_get(); + u32 vpts = timestamp_vpts_get(); + u32 apts = timestamp_apts_get(); + + pr_info("%s pts:%d.%06d pcr:%d.%06d vpts:%d.%06d apts:%d.%06d\n", + __func__, (vf->pts) / 90000, + ((vf->pts) % 90000) * 1000 / 90, (pcr) / 90000, + ((pcr) % 90000) * 1000 / 90, (vpts) / 90000, + ((vpts) % 90000) * 1000 / 90, (apts) / 90000, + ((apts) % 90000) * 1000 / 90); + } + + if (trickmode_i || trickmode_fffb) + trickmode_duration_count = trickmode_duration; + + if (vf->early_process_fun) { + if (vf->early_process_fun(vf->private_data, vf) == 1) { + /* video_property_changed = true; */ + first_picture = 1; + } + } else { +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) != 0) { + /* check mif enable status, disable post di */ + VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); + VSYNC_WR_MPEG_REG(DI_POST_SIZE, + (32 - 1) | ((128 - 1) << 16)); + VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, + READ_VCBUS_REG(DI_IF1_GEN_REG) & + 0xfffffffe); + } +#endif + } + + timer_count = 0; + if ((vf->width == 0) && (vf->height == 0)) { + amlog_level(LOG_LEVEL_ERROR, + "Video: invalid frame dimension\n"); + ATRACE_COUNTER(__func__, __LINE__); + return; + } + + if (hold_video) { + if (cur_dispbuf != vf) { + new_frame_count++; + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_set(vf->pts); + last_frame_duration = vf->duration; + } else if (last_frame_duration) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_inc(DUR2PTS + (last_frame_duration)); + + vpts_remainder += + DUR2PTS_RM(last_frame_duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + if (vf->type & VIDTYPE_COMPRESS) { + cur_width = vf->compWidth; + cur_height = vf->compHeight; + } else { + cur_width = vf->width; + cur_height = vf->height; + } + video_vf_put(vf); + ATRACE_COUNTER(__func__, __LINE__); + return; + } + } + + if ((cur_dispbuf) && (cur_dispbuf != &vf_local) && (cur_dispbuf != vf) + && (video_property_changed != 2)) { + new_frame_count++; + if (new_frame_count == 1) + first_picture = 1; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { +#ifdef RDMA_RECYCLE_ORDERED_VFRAMES + if (dispbuf_to_put_num < DISPBUF_TO_PUT_MAX) { + dispbuf_to_put[dispbuf_to_put_num] = + cur_dispbuf; + dispbuf_to_put_num++; + } else + video_vf_put(cur_dispbuf); +#else + if (cur_rdma_buf == cur_dispbuf) { + dispbuf_to_put[0] = cur_dispbuf; + dispbuf_to_put_num = 1; + } else + video_vf_put(cur_dispbuf); +#endif + } else { + int i; + + for (i = 0; i < dispbuf_to_put_num; i++) { + if (dispbuf_to_put[i]) { + video_vf_put( + dispbuf_to_put[i]); + dispbuf_to_put[i] = NULL; + } + dispbuf_to_put_num = 0; + } + video_vf_put(cur_dispbuf); + } +#else + video_vf_put(cur_dispbuf); +#endif + if (debug_flag & DEBUG_FLAG_LATENCY) { + vf->ready_clock[3] = sched_clock(); + pr_info( + "video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n", + func_div(vf->ready_clock[3], 1000), + func_div(vf->ready_clock[2], 1000), + func_div(vf->ready_clock[1], 1000), + func_div(vf->ready_clock[0], 1000)); + cur_dispbuf->ready_clock[4] = sched_clock(); + clk_array = cur_dispbuf->ready_clock; + pr_info("video put latency %lld ms, video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n", + func_div(*(clk_array + 4), 1000), + func_div(*(clk_array + 3), 1000), + func_div(*(clk_array + 2), 1000), + func_div(*(clk_array + 1), 1000), + func_div(*clk_array, 1000)); + } + } else + first_picture = 1; + + if (video_property_changed) { + property_changed_true = 2; + video_property_changed = 0; + force_toggle = true; + } + if (property_changed_true > 0) { + property_changed_true--; + force_toggle = true; + } + + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && first_picture) + pr_info("first picture {%d,%d} pts:%x,\n", + vf->width, vf->height, vf->pts); + + /* switch buffer */ + post_canvas = vf->canvas0Addr; + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && + (vf->type & VIDTYPE_COMPRESS)) { + VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4); + } + if ((vf->canvas0Addr != 0) +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + && ((DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) == 0) + /* check di_post_viu_link */ +#endif + ) { + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (vf->canvas0Addr != (u32)-1) { + canvas_copy(vf->canvas0Addr & 0xff, + disp_canvas_index[rdma_canvas_id][0]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][1]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][2]); + } else { + vframe_canvas_set(&vf->canvas0_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][0]); + } + if (is_mvc || process_3d_type) { + if (vf->canvas1Addr != (u32)-1) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[rdma_canvas_id][3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas1_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][3]); + } + } + + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode == 1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + } + if (cur_frame_par + && (process_3d_type & MODE_3D_ENABLE) + && (process_3d_type & MODE_3D_TO_2D_R) + && (cur_frame_par->vpp_2pic_mode + == VPP_SELECT_PIC1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (is_mvc) { + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } + } + next_rdma_canvas_id = rdma_canvas_id ? 0 : 1; +#else + canvas_copy(vf->canvas0Addr & 0xff, disp_canvas_index[0]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[1]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[2]); + if (is_mvc || process_3d_type) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[5]); + } + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode == 1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); + } +#endif + } + /* set video PTS */ + if (cur_dispbuf != vf) { + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_set(vf->pts); + } else if (cur_dispbuf) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_inc(DUR2PTS + (cur_dispbuf->duration)); + + vpts_remainder += + DUR2PTS_RM(cur_dispbuf->duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + vf->type_backup = vf->type; + } + + if (cur_dispbuf && + (cur_dispbuf->ratio_control & + DISP_RATIO_ADAPTED_PICMODE)) { + if (vf && (cur_dispbuf->ratio_control + == vf->ratio_control) + && memcmp(&cur_dispbuf->pic_mode, + &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + else if (memcmp(&cur_dispbuf->pic_mode, + &gPic_info[0], + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + } + + if ((last_process_3d_type != process_3d_type) + || (last_el_status != vf_with_el)) + force_toggle = true; + + /* enable new config on the new frames */ + if (first_picture || force_toggle || + (cur_dispbuf && + ((cur_dispbuf->bufWidth != vf->bufWidth) || + (cur_dispbuf->width != vf->width) || + (cur_dispbuf->height != vf->height) || + (cur_dispbuf->bitdepth != vf->bitdepth) || + #if defined(CONFIG_AMLOGIC_MEDIA_TVIN) + (cur_dispbuf->trans_fmt != vf->trans_fmt) || + #endif + (cur_dispbuf->ratio_control != vf->ratio_control) || + ((cur_dispbuf->type_backup & VIDTYPE_INTERLACE) != + (vf->type_backup & VIDTYPE_INTERLACE)) || + (cur_dispbuf->type != vf->type)))) { + int iret; + + last_process_3d_type = process_3d_type; + atomic_inc(&video_sizechange); + wake_up_interruptible(&amvideo_sizechange_wait); + amlog_mask(LOG_MASK_FRAMEINFO, + "%s %dx%d ar=0x%x\n", + ((vf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) ? "interlace-top" + : ((vf->type & VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_BOTTOM) + ? "interlace-bottom" : "progressive", vf->width, + vf->height, vf->ratio_control); +#if defined(CONFIG_AMLOGIC_MEDIA_TVIN) + amlog_mask(LOG_MASK_FRAMEINFO, + "%s trans_fmt=%u\n", __func__, vf->trans_fmt); + +#endif + next_frame_par = (&frame_parms[0] == next_frame_par) ? + &frame_parms[1] : &frame_parms[0]; + + update_layer_info(0); + iret = vpp_set_filters( + &glayer_info[0], vf, + next_frame_par, vinfo, + (is_dolby_vision_on() && + is_dolby_vision_stb_mode()), 1); + + memcpy(&gPic_info[0], &vf->pic_mode, + sizeof(struct vframe_pic_mode_s)); + + if ((iret == VppFilter_Success_and_Changed) + || (iret == VppFilter_Changed_but_Hold)) + video_property_changed = 1; + + if (iret == VppFilter_Changed_but_Hold) { + video_notify_flag |= + VIDEO_NOTIFY_NEED_NO_COMP; + vpp_hold_setting_cnt++; + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("toggle_frame vpp hold setting cnt: %d\n", + vpp_hold_setting_cnt); + } else {/* apply new vpp settings */ + if ((next_frame_par->vscale_skip_count <= 1) + && (vf->type & VIDTYPE_SUPPORT_COMPRESS)) { + video_notify_flag |= + VIDEO_NOTIFY_NEED_NO_COMP; + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("disable no compress mode\n"); + } + vpp_hold_setting_cnt = 0; + frame_par_ready_to_set = 1; + } + + if (((vf->width > 1920) && (vf->height > 1088)) || + ((vf->type & VIDTYPE_COMPRESS) && + (vf->compWidth > 1920) && + (vf->compHeight > 1080))) { + if (vpu_clk_level == 0) { + vpu_clk_level = 1; + spin_lock_irqsave(&lock, flags); + vpu_delay_work_flag |= + VPU_DELAYWORK_VPU_CLK; + spin_unlock_irqrestore(&lock, flags); + } + } else { + if (vpu_clk_level == 1) { + vpu_clk_level = 0; + spin_lock_irqsave(&lock, flags); + vpu_delay_work_flag |= + VPU_DELAYWORK_VPU_CLK; + spin_unlock_irqrestore(&lock, flags); + } + } + } + + /* if el is unnecessary, afbc2 need to be closed */ + if ((last_el_status == 1) && (vf_with_el == 0)) + need_disable_vd2 = true; + + if (((vf->type & VIDTYPE_MVC) == 0) + && last_mvc_status) + need_disable_vd2 = true; + + last_el_status = vf_with_el; + + if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && + ((!property_changed_true) || (vf != cur_dispbuf))) { + if (disable_video == VIDEO_DISABLE_FORNEXT) { + EnableVideoLayer(); + disable_video = VIDEO_DISABLE_NONE; + } + if (first_picture && (disable_video != VIDEO_DISABLE_NORMAL)) { + EnableVideoLayer(); + if ((vf->type & VIDTYPE_MVC) || + (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) + EnableVideoLayer2(); + else if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else if (need_disable_vd2) + DisableVideoLayer2(); + } + } + if (cur_dispbuf && (cur_dispbuf->type != vf->type)) { + if ((vf->type & VIDTYPE_MVC) || + (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) + EnableVideoLayer2(); + else { + if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else if (need_disable_vd2) + DisableVideoLayer2(); + } + } + cur_dispbuf = vf; + if (cur_dispbuf && (cur_dispbuf->type & VIDTYPE_MVC)) + last_mvc_status = true; + else + last_mvc_status = false; + + if (first_picture) { + frame_par_ready_to_set = 1; + first_frame_toggled = 1; + +#ifdef VIDEO_PTS_CHASE + av_sync_flag = 0; +#endif + } + if (cur_dispbuf != &vf_local) + video_keeper_new_frame_notify(); + + if ((vf != &vf_local) && (vf) && !vsync_pts_aligned) { +#ifdef PTS_TRACE_DEBUG + pr_info("####timestamp_pcrscr_get() = 0x%x, vf->pts = 0x%x, vsync_pts_inc = %d\n", + timestamp_pcrscr_get(), vf->pts, vsync_pts_inc); +#endif + if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc)) + && ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) { + vsync_pts_align = vsync_pts_inc / 4 - + (timestamp_pcrscr_get() - vf->pts); + vsync_pts_aligned = true; +#ifdef PTS_TRACE_DEBUG + pts_trace_his_rd = 0; + pr_info("####vsync_pts_align set to %d\n", + vsync_pts_align); +#endif + } + } + if (stop_update) + frame_par_ready_to_set = 0; + ATRACE_COUNTER(__func__, 0); +} + +static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) +{ + u32 r; + u32 vphase, vini_phase, vformatter; + 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; + bool is_mvc = false; + u8 burst_len = 1; + + if (vf == NULL) { + pr_info("%s vf NULL, return\n", __func__); + return; + } + + type = vf->type; + if (type & VIDTYPE_MVC) + is_mvc = true; + + pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + 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; +#ifdef TV_REVERSE + if (reverse) + r |= (1<<26) | (1<<27); +#endif + if (vf->bitdepth & BITDEPTH_SAVING_MODE) + r |= (1<<28); /* mem_saving_mode */ + if (type & VIDTYPE_SCATTER) + r |= (1<<29); + VSYNC_WR_MPEG_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(AFBC_ENABLE, r); + + r = 0x100; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + VSYNC_WR_MPEG_REG(AFBC_CONV_CTRL, r); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + VSYNC_WR_MPEG_REG(AFBC_DEC_DEF_COLOR, + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ + + r = 0; +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + } else +#endif + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << + VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << + VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + } + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + AFBCDEC_IQUANT_ENABLE, 0); + } + + vd1_path_select(true); + + VSYNC_WR_MPEG_REG( + VD1_IF0_GEN_REG + cur_dev->viu_off, 0); + return; + + } else { + if ((vf->bitdepth & BITDEPTH_Y10) && + (!frame_par->nocomp)) { + if (vf->type & VIDTYPE_VIU_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( + G12_VD1_IF0_GEN_REG3, + (bit_mode & 0x3), 8, 2); + if (is_mvc) + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (bit_mode & 0x3), 8, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VD1_IF0_GEN_REG3 + + cur_dev->viu_off, + (bit_mode & 0x3), 8, 2); + if (is_mvc) + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG3 + + cur_dev->viu_off, + (bit_mode & 0x3), 8, 2); + } +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + 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 + vd1_path_select(false); + VSYNC_WR_MPEG_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 (debug_flag & 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) + r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; + + /*enable go field reset default according to vlsi*/ + r |= VDIF_RESET_ON_GO_FIELD; + VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + cur_dev->viu_off, r); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_GEN_REG + cur_dev->viu_off, r); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (type & VIDTYPE_VIU_NV21) { + VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 + + cur_dev->viu_off, 1, 0, 1); + } else { + VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 + + cur_dev->viu_off, 0, 0, 1); + } +#ifdef TV_REVERSE + if (reverse) { + VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + + cur_dev->viu_off), 0xf, 2, 4); + if (is_mvc) + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0xf, 2, 4); + } else { + VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + + cur_dev->viu_off), 0, 2, 4); + if (is_mvc) + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0, 2, 4); + } +#endif + } + /* #endif */ + + /* chroma formatter */ + if (type & VIDTYPE_VIU_444) { + VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_1_1); + if (is_mvc) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_1_1); + } else if (type & VIDTYPE_VIU_FIELD) { + vini_phase = 0xc << VFORMATTER_INIPHASE_BIT; + vphase = + ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << + VFORMATTER_PHASE_BIT; + + /*vlsi suggest only for yuv420 vformatter shold be 1*/ + if (type & VIDTYPE_VIU_NV21) + vformatter = VFORMATTER_EN; + else + vformatter = 0; + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + ((type & VIDTYPE_VIU_422) ? + VFORMATTER_RPTLINE0_EN : + VFORMATTER_ALWAYS_RPT) | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + ((type & VIDTYPE_VIU_422) ? + 0 : + VFORMATTER_EN)); + pr_debug("\tvd1 set fmt(dovi tv)\n"); + } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && + (vf->height >= 2160) && + (type & VIDTYPE_VIU_422)) { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | vini_phase | vphase); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | vini_phase | vphase | + vformatter); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + vformatter); + } + } else { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + vformatter); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + vformatter); + } + } else if (type & VIDTYPE_MVC) { + VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + if (is_mvc) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | (0xa << + VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + } else if ((type & VIDTYPE_INTERLACE) + && (((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))) { + VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | (0xe << + VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + if (is_mvc) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + } else { + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xa << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + } + if (is_mvc) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xa << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if ((is_meson_txlx_cpu() + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) + && is_dolby_vision_on() + && is_dolby_vision_stb_mode() + && (vf->source_type == + VFRAME_SOURCE_TYPE_OTHERS)) + VSYNC_WR_MPEG_REG_BITS( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + 1, 29, 1); +#endif + /* 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 (type & VIDTYPE_MVC) { + loop = 0x11; + if (is_need_framepacking_output()) + pat = 0; + else + pat = 0x80; + } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + loop = 0x11; + pat <<= 4; + } else + loop = 0; + + VSYNC_WR_MPEG_REG( + VD1_IF0_RPT_LOOP + cur_dev->viu_off, + (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_IF0_RPT_LOOP + cur_dev->viu_off, + (loop << VDIF_CHROMA_LOOP1_BIT) | + (loop << VDIF_LUMA_LOOP1_BIT) | + (loop << VDIF_CHROMA_LOOP0_BIT) | + (loop << VDIF_LUMA_LOOP0_BIT)); + + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); + + if (type & VIDTYPE_MVC) { + if (is_need_framepacking_output()) + pat = 0; + else + pat = 0x88; + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, 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 */ + if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (1 << 8) | + /* toggle pic 0 and 1, use pic1 first*/ + (0x01)); + /* loop pattern */ + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (1 << 8) | + /* toggle pic 0 and 1,use pic1 first */ + (0x01)); + /* loop pattern */ + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (2 << 8) | + /* toggle pic 0 and 1, use pic0 first */ + (0x01)); + /* loop pattern */ + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (2 << 8) | + /* toggle pic 0 and 1, use pic0 first */ + (0x01)); + /* loop pattern */ + } + } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { + /*FA LR/TB output , do nothing*/ + } else { + if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + if (is_mvc) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + if (is_mvc) { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } + } + } +} + +static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) +{ + u32 r; + u32 vphase, vini_phase; + 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; + u8 burst_len = 1; + + if (!vf) { + pr_err("%s vf is NULL\n", __func__); + return; + } + + type = vf->type; + pr_debug("set dcu for vd2 %p, type:0x%x\n", vf, type); + last_el_w = (vf->type + & VIDTYPE_COMPRESS) ? + vf->compWidth : + vf->width; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + 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; + +#ifdef TV_REVERSE + if (reverse) + r |= (1<<26) | (1<<27); +#endif + 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_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_ENABLE, r); + + r = 0x100; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + VSYNC_WR_MPEG_REG(VD2_AFBC_DEC_DEF_COLOR, + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + + /* chroma formatter */ + r = HFORMATTER_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + r |= HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + } else +#endif + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << + VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << + VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, 0); + } + + vd2_path_select(true); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + + cur_dev->viu_off, 0); + return; + } else { + if ((vf->bitdepth & BITDEPTH_Y10) && + (!frame_par->nocomp)) { + if (vf->type & VIDTYPE_VIU_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(false); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (bit_mode & 0x3), 8, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG3 + cur_dev->viu_off, + (bit_mode&0x3), 8, 2); + } + if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1)) + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + if (type & VIDTYPE_VIU_NV21) + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 1, 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 0, 0, 1); + } + } + + 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 (debug_flag & 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) + r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; + + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, r); + +#ifdef TV_REVERSE + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (reverse) { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0xf, 2, 4); + } else { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0, 2, 4); + } + } +#endif + + /* chroma formatter */ + if (type & VIDTYPE_VIU_444) { + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_1_1); + } else if (type & VIDTYPE_VIU_FIELD) { + vini_phase = 0xc << VFORMATTER_INIPHASE_BIT; + vphase = + ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << + VFORMATTER_PHASE_BIT; + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + pr_debug("\tvd2 set fmt(dovi tv)\n"); + } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && + (vf->height >= 2160) && + (type & VIDTYPE_VIU_422)) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | vini_phase | vphase | + VFORMATTER_EN); + } + } else if (type & VIDTYPE_MVC) { + VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | (0xa << + VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + } else if ((type & VIDTYPE_INTERLACE) + && + (((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))) { + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + pr_info("\tvd2 set fmt(dovi tv)\n"); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + pr_info("\tvd2 set fmt(dovi:%d)\n", + /*is_dolby_vision_on()*/0); + } + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if ((is_meson_txlx_cpu() + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) + && is_dolby_vision_on() + && is_dolby_vision_stb_mode() + && (vf->source_type == + VFRAME_SOURCE_TYPE_OTHERS)) + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + 1, 29, 1); +#endif + /* 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 (type & VIDTYPE_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_IF0_RPT_LOOP + cur_dev->viu_off, + (loop << VDIF_CHROMA_LOOP1_BIT) | + (loop << VDIF_LUMA_LOOP1_BIT) | + (loop << VDIF_CHROMA_LOOP0_BIT) | + (loop << VDIF_LUMA_LOOP0_BIT)); + + if (type & VIDTYPE_MVC) + pat = 0x88; + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); + + if (platform_type == 0) { + /* picture 0/1 control */ + if (((type & VIDTYPE_INTERLACE) == 0) && + ((type & VIDTYPE_VIU_FIELD) == 0) && + ((type & VIDTYPE_MVC) == 0)) { + /* progressive frame in two pictures */ + + } else { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); + } + } else { + /* picture 0/1 control */ + if ((((type & VIDTYPE_INTERLACE) == 0) && + ((type & VIDTYPE_VIU_FIELD) == 0) && + ((type & VIDTYPE_MVC) == 0)) || + (next_frame_par->vpp_2pic_mode & 0x3)) { + /* progressive frame in two pictures */ + + } else { + if (next_frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } + } + } +} + +static int detect_vout_type(void) +{ + 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; +} + +#ifdef INTERLACE_FIELD_MATCH_PROCESS +static inline bool interlace_field_type_need_match(int vout_type, + struct vframe_s *vf) +{ + if (DUR2PTS(vf->duration) != vsync_pts_inc) + return false; + + if ((vout_type == VOUT_TYPE_TOP_FIELD) && + ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_BOTTOM)) + return true; + else if ((vout_type == VOUT_TYPE_BOT_FIELD) && + ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP)) + return true; + + return false; +} +#endif + +static 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; +} + +/* add a new function to check if current display frame has been*/ +/*displayed for its duration */ +static inline bool duration_expire(struct vframe_s *cur_vf, + struct vframe_s *next_vf, u32 dur) +{ + u32 pts; + s32 dur_disp; + static s32 rpt_tab_idx; + static const u32 rpt_tab[4] = { 0x100, 0x100, 0x300, 0x300 }; + + /* do not switch to new frames in none-normal speed */ + if (vsync_slow_factor > 1000) + return false; + + if ((cur_vf == NULL) || (cur_dispbuf == &vf_local)) + return true; + + pts = next_vf->pts; + if (pts == 0) + dur_disp = DUR2PTS(cur_vf->duration); + else + dur_disp = pts - timestamp_vpts_get(); + + if ((dur << 8) >= (dur_disp * rpt_tab[rpt_tab_idx & 3])) { + rpt_tab_idx = (rpt_tab_idx + 1) & 3; + return true; + } else + return false; +} + +#define VPTS_RESET_THRO + +#ifdef PTS_LOGGING +static inline void vpts_perform_pulldown(struct vframe_s *next_vf, + bool *expired) +{ + int pattern_range, expected_curr_interval; + int expected_prev_interval; + int next_vf_nextpts = 0; + + /* Dont do anything if we have invalid data */ + if (!next_vf || !next_vf->pts) + return; + if (next_vf->next_vf_pts_valid) + next_vf_nextpts = next_vf->next_vf_pts; + + switch (pts_pattern_detected) { + case PTS_32_PATTERN: + pattern_range = PTS_32_PATTERN_DETECT_RANGE; + switch (pre_pts_trace) { + case 3: + expected_prev_interval = 3; + expected_curr_interval = 2; + break; + case 2: + expected_prev_interval = 2; + expected_curr_interval = 3; + break; + default: + return; + } + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_32_PATTERN_DURATION; + break; + case PTS_22_PATTERN: + if (pre_pts_trace != 2) + return; + pattern_range = PTS_22_PATTERN_DETECT_RANGE; + expected_prev_interval = 2; + expected_curr_interval = 2; + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_22_PATTERN_DURATION; + break; + case PTS_41_PATTERN: + /* TODO */ + default: + return; + } + + /* We do nothing if we dont have enough data*/ + if (pts_pattern[pts_pattern_detected] != pattern_range) + return; + + if (*expired) { + if (pts_trace < expected_curr_interval) { + /* 2323232323..2233..2323, prev=2, curr=3,*/ + /* check if next frame will toggle after 3 vsyncs */ + /* 22222...22222 -> 222..2213(2)22...22 */ + /* check if next frame will toggle after 3 vsyncs */ + int nextPts = timestamp_pcrscr_get() + vsync_pts_align; + + if (/*((int)(nextPts + expected_prev_interval * */ + /*vsync_pts_inc - next_vf->next_vf_pts) < 0) && */ + ((int)(nextPts + (expected_prev_interval + 1) * + vsync_pts_inc - next_vf_nextpts) >= 0)) { + *expired = false; + if (pts_log_enable[PTS_32_PATTERN] + || pts_log_enable[PTS_22_PATTERN]) + pr_info("hold frame for pattern: %d", + pts_pattern_detected); + } + + /* here need to escape a vsync */ + if (timestamp_pcrscr_get() > + (next_vf->pts + vsync_pts_inc)) { + *expired = true; + pts_escape_vsync = 1; + if (pts_log_enable[PTS_32_PATTERN] + || pts_log_enable[PTS_22_PATTERN]) + pr_info("escape a vsync pattern: %d", + pts_pattern_detected); + } + } + } else { + if (pts_trace == expected_curr_interval) { + /* 23232323..233223...2323 curr=2, prev=3 */ + /* check if this frame will expire next vsyncs and */ + /* next frame will expire after 3 vsyncs */ + /* 22222...22222 -> 222..223122...22 */ + /* check if this frame will expire next vsyncs and */ + /* next frame will expire after 2 vsyncs */ + int nextPts = timestamp_pcrscr_get() + vsync_pts_align; + + if (((int)(nextPts + vsync_pts_inc - next_vf->pts) + >= 0) && + ((int)(nextPts + + vsync_pts_inc * (expected_prev_interval - 1) + - next_vf_nextpts) < 0) && + ((int)(nextPts + expected_prev_interval * + vsync_pts_inc - next_vf_nextpts) >= 0)) { + *expired = true; + if (pts_log_enable[PTS_32_PATTERN] + || pts_log_enable[PTS_22_PATTERN]) + pr_info("pull frame for pattern: %d", + pts_pattern_detected); + } + } + } +} +#endif + +static inline bool vpts_expire(struct vframe_s *cur_vf, + struct vframe_s *next_vf, + int toggled_cnt) +{ + u32 pts; +#ifdef VIDEO_PTS_CHASE + u32 vid_pts, scr_pts; +#endif + u32 systime; + u32 adjust_pts, org_vpts; + bool expired; + + if (next_vf == NULL) + return false; + + if (videopeek) { + videopeek = false; + pr_info("video peek toogle the first frame\n"); + return true; + } + + if (debug_flag & DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC) + return true; + if (/*(cur_vf == NULL) || (cur_dispbuf == &vf_local) ||*/ debugflags & + DEBUG_FLAG_FFPLAY) + return true; + + if ((freerun_mode == FREERUN_NODUR) || hdmi_in_onvideo) + return true; + /*freerun for game mode*/ + if (next_vf->flag & VFRAME_FLAG_GAME_MODE) + return true; + + if (step_enable) { + if (step_flag) + return false; + if (!step_flag) { + step_flag = 1; + return true; + } + } + + if ((trickmode_i == 1) || ((trickmode_fffb == 1))) { + if (((atomic_read(&trickmode_framedone) == 0) + || (trickmode_i == 1)) && (!to_notify_trick_wait) + && (trickmode_duration_count <= 0)) { + return true; + } else + return false; + } + if (omx_secret_mode && (!omx_run || !omx_drop_done)) + return false; + + if (next_vf->duration == 0) + + return true; + + systime = timestamp_pcrscr_get(); + pts = next_vf->pts; + + if (((pts == 0) && (cur_dispbuf != &vf_local)) + || (freerun_mode == FREERUN_DUR)) { + pts = + timestamp_vpts_get() + + (cur_vf ? DUR2PTS(cur_vf->duration) : 0); + } + /* check video PTS discontinuity */ + else if ((enable_video_discontinue_report) && + (first_frame_toggled) && + (abs(systime - pts) > tsync_vpts_discontinuity_margin()) && + ((next_vf->flag & VFRAME_FLAG_NO_DISCONTINUE) == 0)) { + /* + * if paused ignore discontinue + */ + if (!timestamp_pcrscr_enable_state() && + tsync_get_mode() != TSYNC_MODE_PCRMASTER) { + /*pr_info("video pts discontinue, + * but pcrscr is disabled, + * return false\n"); + */ + return false; + } + pts = + timestamp_vpts_get() + + (cur_vf ? DUR2PTS(cur_vf->duration) : 0); + /* pr_info("system=0x%x vpts=0x%x\n", systime,*/ + /*timestamp_vpts_get()); */ + if ((int)(systime - pts) >= 0) { + if (next_vf->pts != 0) + tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY, + next_vf->pts); + else if (next_vf->pts == 0 && + (tsync_get_mode() != TSYNC_MODE_PCRMASTER)) + tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY, + pts); + + /* pr_info("discontinue, + * systime=0x%x vpts=0x%x next_vf->pts = 0x%x\n", + * systime, + * pts, + * next_vf->pts); + */ + + /* pts==0 is a keep frame maybe. */ + if (systime > next_vf->pts || next_vf->pts == 0) + return true; + if (omx_secret_mode == true + && cur_omx_index >= next_vf->omx_index) + return true; + + return false; + } else if (omx_secret_mode == true + && cur_omx_index >= next_vf->omx_index) { + return true; + } else if (tsync_check_vpts_discontinuity(pts) && + tsync_get_mode() == TSYNC_MODE_PCRMASTER) { + /* in pcrmaster mode and pcr clk was used by tync, + * when the stream was replayed, the pcr clk was + * changed to the head of the stream. in this case, + * we send the "VIDEO_TSTAMP_DISCONTINUITY" signal + * to notify tsync and adjust the sysclock to + * make playback smooth. + */ + if (next_vf->pts != 0) + tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY, + next_vf->pts); + else if (next_vf->pts == 0) { + tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY, + pts); + return true; + } + } + } else if (omx_run + && omx_secret_mode + && (omx_pts + omx_pts_interval_upper < next_vf->pts) + && (abs(omx_pts_set_index - next_vf->omx_index) <= 16) + && (omx_pts_set_index >= next_vf->omx_index)) { + pr_info("omx, omx_pts=%d omx_pts_set_index=%d pts=%d omx_index=%d\n", + omx_pts, + omx_pts_set_index, + next_vf->pts, + next_vf->omx_index); + return true; + } + + if (vsync_pts_inc_upint && (!freerun_mode)) { + struct vframe_states frame_states; + u32 delayed_ms, t1, t2; + + delayed_ms = + calculation_stream_delayed_ms(PTS_TYPE_VIDEO, &t1, &t2); + if (video_vf_get_states(&frame_states) == 0) { + u32 pcr = timestamp_pcrscr_get(); + u32 vpts = timestamp_vpts_get(); + u32 diff = pcr - vpts; + + if (delayed_ms > 200) { + vsync_freerun++; + if (pcr < next_vf->pts + || pcr < vpts + next_vf->duration) { + if (next_vf->pts > 0) { + timestamp_pcrscr_set + (next_vf->pts); + } else { + timestamp_pcrscr_set(vpts + + next_vf->duration); + } + } + return true; + } else if ((frame_states.buf_avail_num >= 3) + && diff < vsync_pts_inc << 2) { + vsync_pts_inc_adj = + vsync_pts_inc + (vsync_pts_inc >> 2); + vsync_pts_125++; + } else if ((frame_states.buf_avail_num >= 2 + && diff < vsync_pts_inc << 1)) { + vsync_pts_inc_adj = + vsync_pts_inc + (vsync_pts_inc >> 3); + vsync_pts_112++; + } else if (frame_states.buf_avail_num >= 1 + && diff < vsync_pts_inc - 20) { + vsync_pts_inc_adj = vsync_pts_inc + 10; + vsync_pts_101++; + } else { + vsync_pts_inc_adj = 0; + vsync_pts_100++; + } + } + } + +#ifdef VIDEO_PTS_CHASE + vid_pts = timestamp_vpts_get(); + scr_pts = timestamp_pcrscr_get(); + vid_pts += vsync_pts_inc; + + if (av_sync_flag) { + if (vpts_chase) { + if ((abs(vid_pts - scr_pts) < 6000) + || (abs(vid_pts - scr_pts) > 90000)) { + vpts_chase = 0; + pr_info("leave vpts chase mode, diff:%d\n", + vid_pts - scr_pts); + } + } else if ((abs(vid_pts - scr_pts) > 9000) + && (abs(vid_pts - scr_pts) < 90000)) { + vpts_chase = 1; + if (vid_pts < scr_pts) + vpts_chase_pts_diff = 50; + else + vpts_chase_pts_diff = -50; + vpts_chase_counter = + ((int)(scr_pts - vid_pts)) / vpts_chase_pts_diff; + pr_info("enter vpts chase mode, diff:%d\n", + vid_pts - scr_pts); + } else if (abs(vid_pts - scr_pts) >= 90000) { + pr_info("video pts discontinue, diff:%d\n", + vid_pts - scr_pts); + } + } else + vpts_chase = 0; + + if (vpts_chase) { + u32 curr_pts = + scr_pts - vpts_chase_pts_diff * vpts_chase_counter; + + /* pr_info("vchase pts %d, %d, %d, %d, %d\n",*/ + /*curr_pts, scr_pts, curr_pts-scr_pts, vid_pts, vpts_chase_counter); */ + return ((int)(curr_pts - pts)) >= 0; + } else { + int aud_start = (timestamp_apts_get() != -1); + + if (!av_sync_flag && aud_start && (abs(scr_pts - pts) < 9000) + && ((int)(scr_pts - pts) < 0)) { + av_sync_flag = 1; + pr_info("av sync ok\n"); + } + return ((int)(scr_pts - pts)) >= 0; + } +#else + if (smooth_sync_enable) { + org_vpts = timestamp_vpts_get(); + if ((abs(org_vpts + vsync_pts_inc - systime) < + M_PTS_SMOOTH_MAX) + && (abs(org_vpts + vsync_pts_inc - systime) > + M_PTS_SMOOTH_MIN)) { + + if (!video_frame_repeat_count) { + vpts_ref = org_vpts; + video_frame_repeat_count++; + } + + if ((int)(org_vpts + vsync_pts_inc - systime) > 0) { + adjust_pts = + vpts_ref + (vsync_pts_inc - + M_PTS_SMOOTH_ADJUST) * + video_frame_repeat_count; + } else { + adjust_pts = + vpts_ref + (vsync_pts_inc + + M_PTS_SMOOTH_ADJUST) * + video_frame_repeat_count; + } + + return (int)(adjust_pts - pts) >= 0; + } + + if (video_frame_repeat_count) { + vpts_ref = 0; + video_frame_repeat_count = 0; + } + } + + expired = (int)(timestamp_pcrscr_get() + vsync_pts_align - pts) >= 0; + +#ifdef PTS_THROTTLE + if (expired && next_vf && next_vf->next_vf_pts_valid && + (vsync_slow_factor == 1) && + next_vf->next_vf_pts && + (toggled_cnt > 0) && + ((int)(timestamp_pcrscr_get() + vsync_pts_inc + + vsync_pts_align - next_vf->next_vf_pts) < 0)) { + expired = false; + } else if (!expired && next_vf && next_vf->next_vf_pts_valid && + (vsync_slow_factor == 1) && + next_vf->next_vf_pts && + (toggled_cnt == 0) && + ((int)(timestamp_pcrscr_get() + vsync_pts_inc + + vsync_pts_align - next_vf->next_vf_pts) >= 0)) { + expired = true; + } +#endif + +#ifdef PTS_LOGGING + if (pts_enforce_pulldown) { + /* Perform Pulldown if needed*/ + vpts_perform_pulldown(next_vf, &expired); + } +#endif + return expired; +#endif +} + +static void vsync_notify(void) +{ + if (video_notify_flag & VIDEO_NOTIFY_TRICK_WAIT) { + wake_up_interruptible(&amvideo_trick_wait); + video_notify_flag &= ~VIDEO_NOTIFY_TRICK_WAIT; + } + if (video_notify_flag & VIDEO_NOTIFY_FRAME_WAIT) { + video_notify_flag &= ~VIDEO_NOTIFY_FRAME_WAIT; + vf_notify_provider(RECEIVER_NAME, + VFRAME_EVENT_RECEIVER_FRAME_WAIT, NULL); + } +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + if (video_notify_flag & VIDEO_NOTIFY_POS_CHANGED) { + video_notify_flag &= ~VIDEO_NOTIFY_POS_CHANGED; + vf_notify_provider(RECEIVER_NAME, + VFRAME_EVENT_RECEIVER_POS_CHANGED, NULL); + } +#endif + if (video_notify_flag & + (VIDEO_NOTIFY_PROVIDER_GET | VIDEO_NOTIFY_PROVIDER_PUT)) { + int event = 0; + + if (video_notify_flag & VIDEO_NOTIFY_PROVIDER_GET) + event |= VFRAME_EVENT_RECEIVER_GET; + if (video_notify_flag & VIDEO_NOTIFY_PROVIDER_PUT) + event |= VFRAME_EVENT_RECEIVER_PUT; + + vf_notify_provider(RECEIVER_NAME, event, NULL); + + video_notify_flag &= + ~(VIDEO_NOTIFY_PROVIDER_GET | VIDEO_NOTIFY_PROVIDER_PUT); + } + if (video_notify_flag & VIDEO_NOTIFY_NEED_NO_COMP) { + /* FIXME: can not use fixed provider name */ + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_NEED_NO_COMP, + (void *)&vpp_hold_setting_cnt); + video_notify_flag &= ~VIDEO_NOTIFY_NEED_NO_COMP; + } +#ifdef CONFIG_CLK81_DFS + check_and_set_clk81(); +#endif + +#ifdef CONFIG_GAMMA_PROC + gamma_adjust(); +#endif + +} + +#ifdef FIQ_VSYNC +static irqreturn_t vsync_bridge_isr(int irq, void *dev_id) +{ + vsync_notify(); + + return IRQ_HANDLED; +} +#endif + +int get_vsync_count(unsigned char reset) +{ + if (reset) + vsync_count = 0; + return vsync_count; +} +EXPORT_SYMBOL(get_vsync_count); + +int get_vsync_pts_inc_mode(void) +{ + return vsync_pts_inc_upint; +} +EXPORT_SYMBOL(get_vsync_pts_inc_mode); + +void set_vsync_pts_inc_mode(int inc) +{ + vsync_pts_inc_upint = inc; +} +EXPORT_SYMBOL(set_vsync_pts_inc_mode); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +void vsync_rdma_process(void) +{ + vsync_rdma_config(); +} +#endif + +/* #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 */ +static enum vmode_e old_vmode = VMODE_MAX; +/* #endif */ +static enum vmode_e new_vmode = VMODE_MAX; +static inline bool video_vf_disp_mode_check(struct vframe_s *vf) +{ + struct provider_disp_mode_req_s req; + int ret = -1; + + req.vf = vf; + req.disp_mode = 0; + req.req_mode = 1; + + if (is_dolby_vision_enable()) { + ret = vf_notify_provider_by_name("dv_vdin", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + if (ret == -1) + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + } else + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + if ((req.disp_mode == VFRAME_DISP_MODE_OK) || + (req.disp_mode == VFRAME_DISP_MODE_NULL)) + return false; + /*whether need to check pts??*/ + video_vf_put(vf); + return true; +} +static enum vframe_disp_mode_e video_vf_disp_mode_get(struct vframe_s *vf) +{ + struct provider_disp_mode_req_s req; + int ret = -1; + + req.vf = vf; + req.disp_mode = 0; + req.req_mode = 0; + + if (is_dolby_vision_enable()) { + ret = vf_notify_provider_by_name("dv_vdin", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + if (ret == -1) + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + } else + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + return req.disp_mode; +} +static inline bool video_vf_dirty_put(struct vframe_s *vf) +{ + if (!vf->frame_dirty) + return false; + if (cur_dispbuf != vf) { + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to vf->pts:0x%x,scr:0x%x,abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_set(vf->pts); + } else if (cur_dispbuf) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc:0x%x,scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_inc( + DUR2PTS(cur_dispbuf->duration)); + + vpts_remainder += + DUR2PTS_RM(cur_dispbuf->duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + } + video_vf_put(vf); + return true; + +} +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION +struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf) +{ + struct vframe_s *toggle_vf = NULL; + int width_bl, width_el; + int height_bl, height_el; + int ret = dolby_vision_update_metadata(vf); + + cur_dispbuf2 = dolby_vision_vf_peek_el(vf); + if (cur_dispbuf2) { + if (cur_dispbuf2->type & VIDTYPE_COMPRESS) { + VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR, + cur_dispbuf2->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR, + cur_dispbuf2->compBodyAddr>>4); + } else { + vframe_canvas_set(&cur_dispbuf2->canvas0_config[0], + cur_dispbuf2->plane_num, + &disp_canvas_index[rdma_canvas_id][3]); + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } + + width_el = (cur_dispbuf2->type + & VIDTYPE_COMPRESS) ? + cur_dispbuf2->compWidth : + cur_dispbuf2->width; + if (!(cur_dispbuf2->type & VIDTYPE_VD2)) { + width_bl = (vf->type + & VIDTYPE_COMPRESS) ? + vf->compWidth : + vf->width; + if (width_el >= width_bl) + width_el = width_bl; + else if (width_el != width_bl / 2) + width_el = width_bl / 2; + } + ori2_start_x_lines = 0; + ori2_end_x_lines = + width_el - 1; + + height_el = (cur_dispbuf2->type + & VIDTYPE_COMPRESS) ? + cur_dispbuf2->compHeight : + cur_dispbuf2->height; + if (!(cur_dispbuf2->type & VIDTYPE_VD2)) { + height_bl = (vf->type + & VIDTYPE_COMPRESS) ? + vf->compHeight : + vf->height; + if (height_el >= height_bl) + height_el = height_bl; + else if (height_el != height_bl / 2) + height_el = height_bl / 2; + } + ori2_start_y_lines = 0; + ori2_end_y_lines = + height_el - 1; + } + if (ret == 0) { + /* setting generated for this frame */ + /* or DOVI in bypass mode */ + toggle_vf = vf; + dolby_vision_set_toggle_flag(1); + } else { + /* fail generating setting for this frame */ + toggle_vf = NULL; + dolby_vision_set_toggle_flag(0); + } + return toggle_vf; +} + +static int dolby_vision_need_wait(void) +{ + struct vframe_s *vf; + + vf = video_vf_peek(); + if (!vf || (dolby_vision_wait_metadata(vf) == 1)) + return 1; + return 0; +} +#endif +/* patch for 4k2k bandwidth issue, skiw mali and vpu mif */ +static void dmc_adjust_for_mali_vpu(unsigned int width, + unsigned int height, bool force_adjust) +{ + if (toggle_count == last_toggle_count) + toggle_same_count++; + else { + last_toggle_count = toggle_count; + toggle_same_count = 0; + } + /*avoid 3840x2160 crop*/ + if ((width >= 2000) && (height >= 1400) && + (((dmc_config_state != 1) && (toggle_same_count < 30)) + || force_adjust)) { + if (0) {/* if (is_dolby_vision_enable()) { */ + /* vpu dmc */ + WRITE_DMCREG( + DMC_AM0_CHAN_CTRL, + 0x85f403f4); + WRITE_DMCREG( + DMC_AM1_CHAN_CTRL, + 0x85f403f4); + WRITE_DMCREG( + DMC_AM2_CHAN_CTRL, + 0x85f403f4); + + /* mali dmc */ + WRITE_DMCREG( + DMC_AXI1_CHAN_CTRL, + 0xff10ff4); + WRITE_DMCREG( + DMC_AXI2_CHAN_CTRL, + 0xff10ff4); + WRITE_DMCREG( + DMC_AXI1_HOLD_CTRL, + 0x08040804); + WRITE_DMCREG( + DMC_AXI2_HOLD_CTRL, + 0x08040804); + } else { + /* vpu dmc */ + WRITE_DMCREG( + DMC_AM1_CHAN_CTRL, + 0x43028); + WRITE_DMCREG( + DMC_AM1_HOLD_CTRL, + 0x18101818); + WRITE_DMCREG( + DMC_AM3_CHAN_CTRL, + 0x85f403f4); + WRITE_DMCREG( + DMC_AM4_CHAN_CTRL, + 0x85f403f4); + /* mali dmc */ + WRITE_DMCREG( + DMC_AXI1_HOLD_CTRL, + 0x10080804); + WRITE_DMCREG( + DMC_AXI2_HOLD_CTRL, + 0x10080804); + } + dmc_config_state = 1; + } else if (((toggle_same_count >= 30) || + ((width < 2000) && (height < 1400))) && + (dmc_config_state != 2)) { + /* vpu dmc */ + WRITE_DMCREG( + DMC_AM0_CHAN_CTRL, + 0x8FF003C4); + WRITE_DMCREG( + DMC_AM1_CHAN_CTRL, + 0x3028); + WRITE_DMCREG( + DMC_AM1_HOLD_CTRL, + 0x18101810); + WRITE_DMCREG( + DMC_AM2_CHAN_CTRL, + 0x8FF003C4); + WRITE_DMCREG( + DMC_AM2_HOLD_CTRL, + 0x3028); + WRITE_DMCREG( + DMC_AM3_CHAN_CTRL, + 0x85f003f4); + WRITE_DMCREG( + DMC_AM4_CHAN_CTRL, + 0x85f003f4); + + /* mali dmc */ + WRITE_DMCREG( + DMC_AXI1_CHAN_CTRL, + 0x8FF00FF4); + WRITE_DMCREG( + DMC_AXI2_CHAN_CTRL, + 0x8FF00FF4); + WRITE_DMCREG( + DMC_AXI1_HOLD_CTRL, + 0x18101810); + WRITE_DMCREG( + DMC_AXI2_HOLD_CTRL, + 0x18101810); + toggle_same_count = 30; + dmc_config_state = 2; + } +} + +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) +{ + 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 (cur_dispbuf2) { + /* + *if (cur_dispbuf2->type + * & VIDTYPE_COMPRESS) + * aligned_mask = 0xffffffc0; + *else + */ + aligned_mask = 0xfffffffc; + } + + { + 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_ - 1; + /* if have el layer, need 2 pixel align by height */ + if (cur_dispbuf2) { + 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 correct_vd2_mif_size_for_DV( + struct vpp_frame_par_s *par, + struct vframe_s *bl_vf) +{ + int width_bl, width_el, line_in_length; + int shift; + + 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 */ + width_el = (cur_dispbuf2->type + & VIDTYPE_COMPRESS) ? + cur_dispbuf2->compWidth : + cur_dispbuf2->width; + width_bl = (bl_vf->type + & VIDTYPE_COMPRESS) ? + bl_vf->compWidth : + bl_vf->width; + if (width_el >= width_bl) + shift = 0; + else + shift = 1; + zoom2_start_x_lines = + par->VPP_hd_start_lines_ >> shift; + line_in_length = + par->VPP_line_in_length_ >> shift; + zoom2_end_x_lines + &= 0xfffffffe; + line_in_length + &= 0xfffffffe; + if (line_in_length > 1) + zoom2_end_x_lines = + zoom2_start_x_lines + + line_in_length - 1; + else + zoom2_end_x_lines = zoom2_start_x_lines; + + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> shift; + if (zoom2_start_y_lines >= zoom2_end_y_lines) + zoom2_end_y_lines = zoom2_start_y_lines; + /* TODO: if el len is 0, need disable bl */ + } +} +#if ENABLE_UPDATE_HDR_FROM_USER +void set_hdr_to_frame(struct vframe_s *vf) +{ + unsigned long flags; + + spin_lock_irqsave(&omx_hdr_lock, flags); + + if (has_hdr_info) { + vf->prop.master_display_colour = vf_hdr; + + //config static signal_type for vp9 + vf->signal_type = (1 << 29) + | (5 << 26) /* unspecified */ + | (0 << 25) /* limit */ + | (1 << 24) /* color available */ + | (9 << 16) /* 2020 */ + | (16 << 8) /* 2084 */ + | (9 << 0); /* 2020 */ + + //pr_info("set_hdr_to_frame %d, signal_type 0x%x", + //vf->prop.master_display_colour.present_flag,vf->signal_type); + } + spin_unlock_irqrestore(&omx_hdr_lock, flags); +} +#endif + +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++; + } + + 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 bool black_threshold_check(u8 id) +{ + struct disp_info_s *layer = NULL; + bool ret = false; + + if (id >= MAX_VD_LAYERS) + return ret; + + if ((black_threshold_width <= 0) + || (black_threshold_height <= 0)) + return ret; + + layer = &glayer_info[id]; + if ((layer->layer_top == 0) + && (layer->layer_left == 0) + && (layer->layer_width <= 1) + && (layer->layer_height <= 1)) + /* special case to do full screen display */ + return ret; + + if ((layer->layer_width <= black_threshold_width) + || (layer->layer_height <= black_threshold_height)) + ret = true; + return ret; +} + +#ifdef TV_3D_FUNCTION_OPEN +inline void switch_3dView_per_vsync(void) +{ + u32 start_aligned, end_aligned, block_len; + u32 FA_enable = process_3d_type & MODE_3D_OUT_FA_MASK; + + if (FA_enable && (toggle_3d_fa_frame == OUT_FA_A_FRAME)) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + if ((process_3d_type & MODE_FORCE_3D_FA_LR) + && (cur_frame_par->vpp_3d_mode == 1)) { + start_aligned = ori_start_x_lines; + end_aligned = ori_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(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(ori_start_y_lines, 4); + end_aligned = + round_up(ori_end_y_lines + 1, 4); + block_len = end_aligned - start_aligned; + block_len = block_len / 8; + VSYNC_WR_MPEG_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 + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + if ((process_3d_type & MODE_FORCE_3D_FA_LR) + && (cur_frame_par->vpp_3d_mode == 1)) { + start_aligned = ori_start_x_lines; + end_aligned = ori_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(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(ori_start_y_lines, 4); + end_aligned = + round_up(ori_end_y_lines + 1, 4); + block_len = end_aligned - start_aligned; + block_len = block_len / 8; + VSYNC_WR_MPEG_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 + + cur_dev->vpp_off, 0, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_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(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + } + } +} +#endif + +#ifdef FIQ_VSYNC +void vsync_fisr_in(void) +#else +static irqreturn_t vsync_isr_in(int irq, void *dev_id) +#endif +{ + int hold_line; + int enc_line; + unsigned char frame_par_di_set = 0; + s32 i, vout_type; + struct vframe_s *vf; + unsigned long flags; +#ifdef CONFIG_TVIN_VDIN + struct vdin_v4l2_ops_s *vdin_ops = NULL; + struct vdin_arg_s arg; +#endif + bool show_nosync = false; + u32 vpp_misc_save, vpp_misc_set; + int first_set = 0; + int toggle_cnt; + struct vframe_s *toggle_vf = NULL; + struct vframe_s *toggle_frame = NULL; + int video1_off_req = 0; + int video2_off_req = 0; + struct vframe_s *cur_dispbuf_back = cur_dispbuf; + static struct vframe_s *pause_vf; + int force_flush = 0; + static u32 interrupt_count; + + if (debug_flag & DEBUG_FLAG_VSYNC_DONONE) + return IRQ_HANDLED; + + if (!hist_test_flag && (cur_dispbuf == &hist_test_vf)) + cur_dispbuf = NULL; + + if (frame_detect_flag == 1 && + receive_frame_count && + frame_detect_time && + !atomic_read(&video_unreg_flag)) { + struct vinfo_s *video_info; + + video_info = get_current_vinfo(); + if (video_frame_detect.interrupt_count == 0) { + interrupt_count = 0; + video_frame_detect.interrupt_count = + frame_detect_time * + video_info->sync_duration_num / + video_info->sync_duration_den; + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("sync_duration_num = %d\n", + video_info->sync_duration_num); + pr_info("sync_duration_den = %d\n", + video_info->sync_duration_den); + } + video_frame_detect.start_receive_count = + receive_frame_count; + } + + interrupt_count++; + + if (interrupt_count == video_frame_detect.interrupt_count + 1) { + u32 receive_count; + u32 expect_frame_count; + + receive_count = receive_frame_count - + video_frame_detect.start_receive_count; + expect_frame_count = + video_frame_detect.interrupt_count * + frame_detect_fps * + video_info->sync_duration_den / + video_info->sync_duration_num / + 1000; + + if (receive_count < expect_frame_count) { + frame_detect_drop_count += + expect_frame_count - + receive_count; + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("drop_count = %d\n", + expect_frame_count - + receive_count); + } + frame_detect_receive_count += + expect_frame_count; + } else + frame_detect_receive_count += receive_count; + + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("expect count = %d\n", + expect_frame_count); + pr_info("receive_count = %d, time = %ds\n", + receive_count, + frame_detect_time); + pr_info("interrupt_count = %d\n", + video_frame_detect.interrupt_count); + pr_info("frame_detect_drop_count = %d\n", + frame_detect_drop_count); + pr_info("frame_detect_receive_count = %d\n", + frame_detect_receive_count); + } + interrupt_count = 0; + memset(&video_frame_detect, 0, + sizeof(struct video_frame_detect_s)); + } + } + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + const char *dev_id_s = (const char *)dev_id; + int dev_id_len = strlen(dev_id_s); + + if (cur_dev == &video_dev[1]) { + if (cur_dev_idx == 0) { + cur_dev = &video_dev[0]; + vinfo = get_current_vinfo(); + vsync_pts_inc = + 90000 * vinfo->sync_duration_den / + vinfo->sync_duration_num; + vsync_pts_inc_scale = vinfo->sync_duration_den; + vsync_pts_inc_scale_base = vinfo->sync_duration_num; + video_property_changed = 1; + pr_info("Change to video 0\n"); + } + } else { + if (cur_dev_idx != 0) { + cur_dev = &video_dev[1]; + vinfo = get_current_vinfo2(); + vsync_pts_inc = + 90000 * vinfo->sync_duration_den / + vinfo->sync_duration_num; + vsync_pts_inc_scale = vinfo->sync_duration_den; + vsync_pts_inc_scale_base = vinfo->sync_duration_num; + video_property_changed = 1; + pr_info("Change to video 1\n"); + } + } + + if ((dev_id_s[dev_id_len - 1] == '2' && cur_dev_idx == 0) || + (dev_id_s[dev_id_len - 1] != '2' && cur_dev_idx != 0)) + return IRQ_HANDLED; + /* pr_info("%s: %s\n", __func__, dev_id_s); */ +#endif + + if (omx_need_drop_frame_num > 0 && !omx_drop_done && omx_secret_mode) { + struct vframe_s *vf = NULL; + + while (1) { + vf = video_vf_peek(); + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable() + && vf && is_dovi_frame(vf)) { + pr_info("vsync_isr_in, ignore the omx %d frames drop for dv frame\n", + omx_need_drop_frame_num); + omx_need_drop_frame_num = 0; + omx_drop_done = true; + break; + } +#endif + if (vf) { + if (omx_need_drop_frame_num >= vf->omx_index) { + //pr_info("vsync drop omx_index %d\n", + //vf->omx_index); + vf = video_vf_get(); + video_vf_put(vf); + } else { + omx_drop_done = true; + break; + } + } else + break; + } + } + + vf = video_vf_peek(); + if ((vf) && ((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0)) { + if ((old_vmode != new_vmode) || (debug_flag == 8)) { + debug_flag = 1; + video_property_changed = 1; + pr_info("detect vout mode change!!!!!!!!!!!!\n"); + old_vmode = new_vmode; + } + } + toggle_cnt = 0; + vsync_count++; + timer_count++; + +#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) + vlock_process(vf);/*need call every vsync*/ +#endif + + switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) { + case 0: + enc_line = (READ_VCBUS_REG(ENCL_INFO_READ) >> 16) & 0x1fff; + break; + case 1: + enc_line = (READ_VCBUS_REG(ENCI_INFO_READ) >> 16) & 0x1fff; + break; + case 2: + enc_line = (READ_VCBUS_REG(ENCP_INFO_READ) >> 16) & 0x1fff; + break; + case 3: + enc_line = (READ_VCBUS_REG(ENCT_INFO_READ) >> 16) & 0x1fff; + break; + } + if (enc_line > vsync_enter_line_max) + vsync_enter_line_max = enc_line; + + if (is_meson_txlx_cpu() && dmc_adjust) { + bool force_adjust = false; + u32 vf_width = 0, vf_height = 0; + struct vframe_s *chk_vf; + + chk_vf = (vf != NULL) ? vf : cur_dispbuf; + if (chk_vf) + force_adjust = + (chk_vf->type & VIDTYPE_VIU_444) ? true : false; + if (chk_vf) { + if (cur_frame_par && + cur_frame_par->nocomp) { + vf_width = chk_vf->width; + vf_height = chk_vf->height; + } else if ((chk_vf->type & VIDTYPE_COMPRESS) + && cur_frame_par + && cur_frame_par->vscale_skip_count) { + vf_width = chk_vf->compWidth; + vf_height = chk_vf->compHeight; + } else { + vf_width = chk_vf->width; + vf_height = chk_vf->height; + } + dmc_adjust_for_mali_vpu( + vf_width, + vf_height, + force_adjust); + } else + dmc_adjust_for_mali_vpu( + 0, 0, force_adjust); + } +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + vsync_rdma_config_pre(); + + if (to_notify_trick_wait) { + atomic_set(&trickmode_framedone, 1); + video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT; + to_notify_trick_wait = false; + goto exit; + } + + if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { + if (video_property_changed) { + enable_rdma_log_count = 5; + enable_rdma_log(1); + } + if (enable_rdma_log_count > 0) + enable_rdma_log_count--; + } +#endif +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + /* check video frame before VECM process */ + if (is_dolby_vision_enable() && vf) + dolby_vision_check_hdr10(vf); +#endif +#ifdef CONFIG_TVIN_VDIN + /* patch for m8 4k2k wifidisplay bandwidth bottleneck */ + if (get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { + vdin_ops = get_vdin_v4l2_ops(); + if (vdin_ops && vdin_ops->tvin_vdin_func) { + arg.cmd = VDIN_CMD_ISR; + vdin_ops->tvin_vdin_func(1, &arg); +#ifdef CONFIG_AM_VIDEO2 + vdin_ops->tvin_vdin_func(0, &arg); +#endif + } + } +#endif + vout_type = detect_vout_type(); + hold_line = calc_hold_line(); + if (vsync_pts_inc_upint) { + if (vsync_pts_inc_adj) { + /* pr_info("adj %d, org %d\n",*/ + /*vsync_pts_inc_adj, vsync_pts_inc); */ + timestamp_pcrscr_inc(vsync_pts_inc_adj); + timestamp_apts_inc(vsync_pts_inc_adj); + } else { + timestamp_pcrscr_inc(vsync_pts_inc + 1); + timestamp_apts_inc(vsync_pts_inc + 1); + } + } else { + if (vsync_slow_factor == 0) { + pr_info("invalid vsync_slow_factor, set to 1\n"); + vsync_slow_factor = 1; + } + + if (vsync_slow_factor == 1) { + timestamp_pcrscr_inc_scale(vsync_pts_inc_scale, + vsync_pts_inc_scale_base); + timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor); + videosync_pcrscr_update(vsync_pts_inc_scale, + vsync_pts_inc_scale_base); + } else if (vsync_slow_factor > 1000) { + u32 inc = (vsync_slow_factor / 1000) + * vsync_pts_inc / 1000; + + timestamp_pcrscr_inc(inc); + timestamp_apts_inc(inc); + } else { + timestamp_pcrscr_inc(vsync_pts_inc / vsync_slow_factor); + timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor); + } + } + if (omx_secret_mode == true) { + u32 system_time = timestamp_pcrscr_get(); + int diff = 0; + unsigned long delta1 = 0; + + diff = system_time - omx_pts; + if (time_setomxpts.tv_sec > 0) { + struct timeval now; + /* time_setomxpts record hwc setomxpts time, */ + /* when check diff between pcr and omx_pts, */ + /* add compensation will let omx_pts and pcr */ + /* is at the some time, more accurate. Also */ + /* remove the compensation when omx_pts */ + /* is not update for a while, in case when */ + /* paused, pcr is not paused */ + do_gettimeofday(&now); + delta1 = (now.tv_sec - time_setomxpts.tv_sec) + * 1000000LL + + (now.tv_usec - time_setomxpts.tv_usec); + if (((diff - omx_pts_interval_upper * 3 / 2) > 0) + || ((diff - omx_pts_interval_lower * 3 / 2) + < 0)) { + time_setomxpts.tv_sec = 0; + time_setomxpts.tv_usec = 0; + pr_info("omxpts is not update for a while,do not need compenstate\n"); + } else { + diff -= delta1 * 90 / 1000; + } + } + + if ((diff - omx_pts_interval_upper) > 0 + || (diff - omx_pts_interval_lower) < 0 + || (omx_pts_set_from_hwc_count < + OMX_MAX_COUNT_RESET_SYSTEMTIME)) { + timestamp_pcrscr_enable(1); + /*pr_info("system_time=%d, omx_pts=%d, diff=%d\n",*/ + /*system_time, omx_pts, diff);*/ + /*add greatest common divisor of duration*/ + /*1500(60fps) 3000(30fps) 3750(24fps) for some video*/ + /*that pts is not evenly*/ + timestamp_pcrscr_set(omx_pts + DURATION_GCD); + } else if (is_dolby_vision_enable() + && ((diff - omx_pts_dv_upper) > 0 + || (diff - omx_pts_dv_lower) < 0)) { + timestamp_pcrscr_set(omx_pts + DURATION_GCD); + } + } else + omx_pts = 0; + if (trickmode_duration_count > 0) + trickmode_duration_count -= vsync_pts_inc; +#ifdef VIDEO_PTS_CHASE + if (vpts_chase) + vpts_chase_counter--; +#endif + + if (slowsync_repeat_enable) + frame_repeat_count++; + + if (smooth_sync_enable) { + if (video_frame_repeat_count) + video_frame_repeat_count++; + } + + if (atomic_read(&video_unreg_flag)) + goto exit; + + if (atomic_read(&video_pause_flag) + && (!((video_global_output == 1) + && (video_enabled != video_status_saved)))) + goto exit; + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { + rdma_canvas_id = next_rdma_canvas_id; +#ifdef VIDEO_PIP + pip_rdma_canvas_id = pip_next_rdma_canvas_id; +#endif + } else { + if (rdma_enable_pre) + goto exit; + + rdma_canvas_id = 0; + next_rdma_canvas_id = 1; +#ifdef VIDEO_PIP + pip_rdma_canvas_id = 0; + pip_next_rdma_canvas_id = 1; +#endif + } + + for (i = 0; i < dispbuf_to_put_num; i++) { + if (dispbuf_to_put[i]) { + video_vf_put(dispbuf_to_put[i]); + dispbuf_to_put[i] = NULL; + } + dispbuf_to_put_num = 0; + } +#ifdef VIDEO_PIP + if (pipbuf_to_put) { + pip_vf_put(pipbuf_to_put); + pipbuf_to_put = NULL; + } +#endif +#endif + + if ((!cur_dispbuf) || (cur_dispbuf == &vf_local)) { + + vf = video_vf_peek(); + + if (vf) { + if (hdmi_in_onvideo == 0) { + if (nopostvideostart == false) + tsync_avevent_locked(VIDEO_START, + (vf->pts) ? vf->pts : + timestamp_vpts_get()); + video_start_post = true; + } + + if (show_first_frame_nosync || show_first_picture) + show_nosync = true; + + if (slowsync_repeat_enable) + frame_repeat_count = 0; + + } else if ((cur_dispbuf == &vf_local) + && (video_property_changed)) { + if (!(blackout | force_blackout)) { + if (cur_dispbuf +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + && ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) + == 0) +#endif + ) { + /* setting video display*/ + /*property in unregister mode */ + u32 cur_index = + READ_VCBUS_REG(VD1_IF0_CANVAS0 + + cur_dev->viu_off); + if ((get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXBB) && + (cur_dispbuf->type & + VIDTYPE_COMPRESS)) { + cur_dispbuf->compHeadAddr = + READ_VCBUS_REG(AFBC_HEAD_BADDR) + << 4; + } else { + cur_dispbuf->canvas0Addr = + cur_index; + } + } + vsync_toggle_frame(cur_dispbuf, __LINE__); + } else + video_property_changed = 0; + } else { + goto SET_FILTER; + } + } + + /* buffer switch management */ + vf = video_vf_peek(); + + /* setting video display property in underflow mode */ + if ((!vf) && cur_dispbuf && (video_property_changed)) + vsync_toggle_frame(cur_dispbuf, __LINE__); + + /*debug info for skip & repeate vframe case*/ + if (!vf) { + underflow++; + ATRACE_COUNTER("underflow", 1); + if (video_dbg_vf&(1<<0)) + dump_vframe_status("vdin0"); + if (video_dbg_vf&(1<<1)) + dump_vframe_status("deinterlace"); + if (video_dbg_vf&(1<<2)) + dump_vframe_status("amlvideo2"); + if (video_dbg_vf&(1<<3)) + dump_vframe_status("ppmgr"); + if (video_dbg_vf&(1<<4)) + dump_vdin_reg(); + } else { + ATRACE_COUNTER("underflow", 0); + } + video_get_vf_cnt = 0; + if (platform_type == 1) { + /* toggle_3d_fa_frame*/ + /* determine the out frame is L or R or blank */ + judge_3d_fa_out_mode(); + } + while (vf) { + if (vpts_expire(cur_dispbuf, vf, toggle_cnt) || show_nosync) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); + if (debug_flag & DEBUG_FLAG_PTS_TRACE) + pr_info("vpts = 0x%x, c.dur=0x%x, n.pts=0x%x, scr = 0x%x, pcr-pts-diff=%d, ptstrace=%d\n", + timestamp_vpts_get(), + (cur_dispbuf) ? + cur_dispbuf->duration : 0, + vf->pts, timestamp_pcrscr_get(), + timestamp_pcrscr_get() - vf->pts + + vsync_pts_align, + pts_trace); + amlog_mask_if(toggle_cnt > 0, LOG_MASK_FRAMESKIP, + "skipped\n"); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable() + && dolby_vision_need_wait()) + break; +#endif +#if ENABLE_UPDATE_HDR_FROM_USER + set_hdr_to_frame(vf); +#endif + + /* + *two special case: + *case1:4k display case,input buffer not enough & + * quickly for display + *case2:input buffer all not OK + */ + if (!(vf && + ((vf->source_type == VFRAME_SOURCE_TYPE_HDMI) || + (vf->source_type == VFRAME_SOURCE_TYPE_CVBS)) && + (video_vf_disp_mode_get(vf) == + VFRAME_DISP_MODE_UNKNOWN) && + (frame_skip_check_cnt++ < 10))) + frame_skip_check_cnt = 0; + else + break; + + vf = video_vf_get(); + if (!vf) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); + break; + } + if (debug_flag & DEBUG_FLAG_LATENCY) { + vf->ready_clock[2] = sched_clock(); + pr_info("video get latency %lld ms vdin put latency %lld ms. first %lld ms.\n", + func_div(vf->ready_clock[2], 1000), + func_div(vf->ready_clock[1], 1000), + func_div(vf->ready_clock[0], 1000)); + } + if (video_vf_dirty_put(vf)) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); + break; + } + if (vf && + ((vf->source_type == VFRAME_SOURCE_TYPE_HDMI) || + (vf->source_type == VFRAME_SOURCE_TYPE_CVBS)) && + video_vf_disp_mode_check(vf)) + break; + force_blackout = 0; + if ((platform_type == 1) || + (platform_type == 0)) { + if (vf) { + if (last_mode_3d != + vf->mode_3d_enable) { + last_mode_3d = + vf->mode_3d_enable; + mode_3d_changed = 1; + } + #if defined(CONFIG_AMLOGIC_MEDIA_TVIN) + video_3d_format = vf->trans_fmt; + #endif + } + } + +#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) + refresh_on_vs(vf); + if (amvecm_on_vs( + (cur_dispbuf != &vf_local) + ? cur_dispbuf : NULL, + vf, CSC_FLAG_CHECK_OUTPUT, + cur_frame_par ? + cur_frame_par->supsc1_hori_ratio : + 0, + cur_frame_par ? + cur_frame_par->supsc1_vert_ratio : + 0) == 1) + break; +#endif + + vsync_toggle_frame(vf, __LINE__); + toggle_frame = vf; +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable()) { + toggle_vf = dolby_vision_toggle_frame(vf); + video_pause_global = 0; + } else +#endif + { + cur_dispbuf2 = NULL; + video_pause_global = 2; + pause_vf = NULL; + } + if (trickmode_fffb == 1) { + trickmode_vpts = vf->pts; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) + != 0) { + atomic_set(&trickmode_framedone, 1); + video_notify_flag |= + VIDEO_NOTIFY_TRICK_WAIT; + } else + #endif + to_notify_trick_wait = true; +#else + atomic_set(&trickmode_framedone, 1); + video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT; +#endif + break; + } + if (slowsync_repeat_enable) + frame_repeat_count = 0; + vf = video_vf_peek(); + if (!vf) + next_peek_underflow++; +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (for_dolby_vision_certification() + && toggle_vf) + break; +#endif + if (debug_flag & DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC) + break; + video_get_vf_cnt++; + if (video_get_vf_cnt >= 2) + video_drop_vf_cnt++; + } else { + ATRACE_COUNTER(MODULE_NAME, __LINE__); + /* check if current frame's duration has expired, + *in this example + * it compares current frame display duration + * with 1/1/1/1.5 frame duration + * every 4 frames there will be one frame play + * longer than usual. + * you can adjust this array for any slow sync + * control as you want. + * The playback can be smoother than previous method. + */ + if (slowsync_repeat_enable) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); + if (duration_expire + (cur_dispbuf, vf, + frame_repeat_count * vsync_pts_inc) + && timestamp_pcrscr_enable_state()) { + amlog_mask(LOG_MASK_SLOWSYNC, + "slow sync toggle,repeat_count = %d\n", + frame_repeat_count); + amlog_mask(LOG_MASK_SLOWSYNC, + "sys.time = 0x%x, video time = 0x%x\n", + timestamp_pcrscr_get(), + timestamp_vpts_get()); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable() + && dolby_vision_need_wait()) + break; +#endif +#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) + refresh_on_vs(vf); + if (amvecm_on_vs( + (cur_dispbuf != &vf_local) + ? cur_dispbuf : NULL, + vf, CSC_FLAG_CHECK_OUTPUT, + cur_frame_par ? + cur_frame_par->supsc1_hori_ratio + : 0, + cur_frame_par ? + cur_frame_par->supsc1_vert_ratio + : 0) == 1) + break; +#endif + vf = video_vf_get(); + if (!vf) { + ATRACE_COUNTER(MODULE_NAME, + __LINE__); + break; + } + vsync_toggle_frame(vf, __LINE__); + toggle_frame = vf; +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable()) + toggle_vf = + dolby_vision_toggle_frame(vf); + else +#endif + cur_dispbuf2 = NULL; + frame_repeat_count = 0; + + vf = video_vf_peek(); + } else if ((cur_dispbuf) && + (cur_dispbuf->duration_pulldown > + vsync_pts_inc)) { + frame_count++; + cur_dispbuf->duration_pulldown -= + PTS2DUR(vsync_pts_inc); + } + } else { + if ((cur_dispbuf) + && (cur_dispbuf->duration_pulldown > + vsync_pts_inc)) { + frame_count++; + cur_dispbuf->duration_pulldown -= + PTS2DUR(vsync_pts_inc); + } + } + /* setting video display property in pause mode */ + if (video_property_changed && cur_dispbuf) { + if (blackout | force_blackout) { + if (cur_dispbuf != &vf_local) + vsync_toggle_frame( + cur_dispbuf, + __LINE__); + } else + vsync_toggle_frame(cur_dispbuf, + __LINE__); + if (is_dolby_vision_enable()) { + pause_vf = cur_dispbuf; + video_pause_global = 1; + } else { + pause_vf = NULL; + video_pause_global = 2; + } + } + if (pause_vf && (video_pause_global == 1) + && is_dolby_vision_enable()) { + toggle_vf = pause_vf; + #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) + dolby_vision_parse_metadata( + cur_dispbuf, 0, false); + dolby_vision_set_toggle_flag(1); + #endif + } + break; + } + + toggle_cnt++; + } + +#ifdef INTERLACE_FIELD_MATCH_PROCESS + if (interlace_field_type_need_match(vout_type, vf)) { + if (field_matching_count++ == FIELD_MATCH_THRESHOLD) { + field_matching_count = 0; + /* adjust system time to get one more field toggle */ + /* at next vsync to match field */ + timestamp_pcrscr_inc(vsync_pts_inc); + } + } else + field_matching_count = 0; +#endif + +SET_FILTER: +#ifdef VIDEO_PIP + vf = pip_vf_peek(); + /* setting video display property in underflow mode */ + if ((!vf) && cur_pipbuf && (pip_property_changed)) + pip_toggle_frame(cur_pipbuf); + if (vf) { + vf = pip_vf_get(); + if (vf) { + if (!vf->frame_dirty) + pip_toggle_frame(vf); + else + pip_vf_put(vf); + } + } +#endif +#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) + amvecm_on_vs( + (cur_dispbuf != &vf_local) + ? cur_dispbuf : NULL, + toggle_frame, + toggle_frame ? CSC_FLAG_TOGGLE_FRAME : 0, + cur_frame_par ? + cur_frame_par->supsc1_hori_ratio : + 0, + cur_frame_par ? + cur_frame_par->supsc1_vert_ratio : + 0); +#endif + /* filter setting management */ + if ((frame_par_ready_to_set) || (frame_par_force_to_set)) { + cur_frame_par = next_frame_par; + frame_par_di_set = 1; + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable()) { + u32 frame_size = 0, h_size, v_size; + u8 pps_state = 0; /* pps no change */ + + /* force toggle when keeping frame after playing */ + if ((cur_dispbuf == &vf_local) + && !toggle_vf + && is_dolby_vision_on()) { + toggle_vf = cur_dispbuf; + dolby_vision_parse_metadata( + cur_dispbuf, 2, false); + dolby_vision_set_toggle_flag(1); + } +/* pause mode was moved to video display property */ + if (cur_frame_par) { + if (frame_par_ready_to_set || frame_par_force_to_set) { + struct vppfilter_mode_s *vpp_filter = + &cur_frame_par->vpp_filter; + 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 && + !cur_frame_par->supsc0_enable && + !cur_frame_par->supsc1_enable && + bypass_pps) + pps_state = 2; /* pps disable */ + else + pps_state = 1; /* pps enable */ + } + if (cur_frame_par->VPP_hd_start_lines_ + >= cur_frame_par->VPP_hd_end_lines_) + h_size = 0; + else + h_size = cur_frame_par->VPP_hd_end_lines_ + - cur_frame_par->VPP_hd_start_lines_ + 1; + h_size /= (cur_frame_par->hscale_skip_count + 1); + if (cur_frame_par->VPP_vd_start_lines_ + >= cur_frame_par->VPP_vd_end_lines_) + v_size = 0; + else + v_size = cur_frame_par->VPP_vd_end_lines_ + - cur_frame_par->VPP_vd_start_lines_ + 1; + v_size /= (cur_frame_par->vscale_skip_count + 1); + frame_size = (h_size << 16) | v_size; + } else if (toggle_vf) { + h_size = (toggle_vf->type & VIDTYPE_COMPRESS) ? + toggle_vf->compWidth : toggle_vf->width; + v_size = (toggle_vf->type & VIDTYPE_COMPRESS) ? + toggle_vf->compHeight : toggle_vf->height; + frame_size = (h_size << 16) | v_size; + } + dolby_vision_process(toggle_vf, frame_size, pps_state); + dolby_vision_update_setting(); + } +#endif + if ((platform_type == 1) || (platform_type == 0)) { + if (mode_3d_changed) { + mode_3d_changed = 0; + frame_par_force_to_set = 1; + } + } + if (cur_dispbuf_back != cur_dispbuf) { + display_frame_count++; + drop_frame_count = receive_frame_count - display_frame_count; + } + if (cur_dispbuf) { + struct f2v_vphase_s *vphase; + u32 vin_type = cur_dispbuf->type & VIDTYPE_TYPEMASK; + { + int need_afbc = (cur_dispbuf->type & VIDTYPE_COMPRESS); + int afbc_need_reset = + video_enabled && + need_afbc && + (!(READ_VCBUS_REG(AFBC_ENABLE) & 0x100)); + /*video on && afbc is off && is compress frame.*/ + if (frame_par_ready_to_set || afbc_need_reset) { + if (cur_frame_par) { + viu_set_dcu(cur_frame_par, cur_dispbuf); + if (cur_dispbuf2) + vd2_set_dcu(cur_frame_par, + cur_dispbuf2); + } + } else if (cur_dispbuf2) { + u32 new_el_w = + (cur_dispbuf2->type + & VIDTYPE_COMPRESS) ? + cur_dispbuf2->compWidth : + cur_dispbuf2->width; + if (new_el_w != last_el_w) { + pr_info("reset vd2 dcu for el change, %d->%d, %p--%p\n", + last_el_w, new_el_w, + cur_dispbuf, cur_dispbuf2); + vd2_set_dcu(cur_frame_par, + cur_dispbuf2); + } + } else { + last_el_w = 0; + last_el_status = 0; + } + } + + if (cur_frame_par && + cur_frame_par->hscale_skip_count) { + VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + VSYNC_WR_MPEG_REG_BITS(VIU_VD2_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ + } + +#ifdef TV_3D_FUNCTION_OPEN + switch_3dView_per_vsync(); +#endif + /* vertical phase */ + vphase = &cur_frame_par->VPP_vf_ini_phase_ + [vpp_phase_table[vin_type] + [vout_type]]; + VSYNC_WR_MPEG_REG( + VPP_VSC_INI_PHASE + cur_dev->vpp_off, + ((u32) (vphase->phase) << 8)); + + if (vphase->repeat_skip >= 0) { + /* skip lines */ + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + cur_dev->vpp_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 + + cur_dev->vpp_off, 4, + VPP_PHASECTL_INIRCVNUMT_BIT, + VPP_PHASECTL_INIRCVNUM_WID); + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + cur_dev->vpp_off, + 1 - vphase->repeat_skip, + VPP_PHASECTL_INIRPTNUMT_BIT, + VPP_PHASECTL_INIRPTNUM_WID); + } + if (force_3d_scaler == 3 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 3, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } else if (force_3d_scaler == 1 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 1, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); + } else if (force_3d_scaler == 2 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 2, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 0, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } + } +#ifdef VIDEO_PIP + if (pip_frame_ready_to_set) + curpip_frame_par = nextpip_frame_par; + + if (cur_pipbuf) { + int need_afbc = (cur_pipbuf->type & VIDTYPE_COMPRESS); + int afbc_need_reset = + video2_enabled && + need_afbc && + (!(READ_VCBUS_REG(VD2_AFBC_ENABLE) & 0x100)); + /*video on && afbc is off && is compress frame.*/ + if (pip_frame_ready_to_set || afbc_need_reset) + pip_set_dcu(curpip_frame_par, cur_pipbuf); + + if (cur_pipbuf && curpip_frame_par) { + if (curpip_frame_par->hscale_skip_count) { + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ + } + proc_vd2_vsc_phase_per_vsync( + curpip_frame_par, cur_pipbuf, vout_type); + } + } + + if (pip_frame_ready_to_set) { + struct scaler_setting_s local_pps; + struct blend_setting_s local_blend; + struct vpp_frame_par_s *par = curpip_frame_par; + + if (cur_pipbuf->type & VIDTYPE_INTERLACE) { + if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) { + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> 1; + zoom2_end_y_lines = + ((par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } else { + zoom2_start_y_lines = + par->VPP_vd_start_lines_; + zoom2_end_y_lines = + par->VPP_vd_end_lines_; + } + } else { + if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) { + zoom2_start_y_lines = + par->VPP_vd_start_lines_; + zoom2_end_y_lines = + par->VPP_vd_end_lines_; + } else { + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> 1; + zoom2_end_y_lines = + ((par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } + } + zoom2_start_x_lines = + par->VPP_hd_start_lines_; + zoom2_end_x_lines = + par->VPP_hd_end_lines_; + config_vd_pps( + 1, par, &local_pps, vinfo); + config_vd_blend( + 1, par, cur_pipbuf, + (legacy_vpp ? 0x1ff : 0x100), &local_blend); + vd2_scaler_setting(&local_pps); + vd2_zoom_display_horz( + cur_pipbuf, + par->hscale_skip_count); + vd2_zoom_display_vert( + cur_pipbuf, + par->vscale_skip_count); + vd2_vpp_blend_setting(&local_blend); + pip_frame_ready_to_set = 0; + } +#endif + + if (((frame_par_ready_to_set) || (frame_par_force_to_set)) && + (cur_frame_par)) { + struct vppfilter_mode_s *vpp_filter = + &cur_frame_par->vpp_filter; + + if (cur_dispbuf) { + u32 zoom_start_y, zoom_end_y; + + correct_vd1_mif_size_for_DV(cur_frame_par); + if (cur_dispbuf->type & VIDTYPE_INTERLACE) { + if (cur_dispbuf->type + & VIDTYPE_COMPRESS) { + /* for vdin afbc and interlace case */ + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_; + zoom_end_y = + cur_frame_par->VPP_vd_end_lines_; + } else if (cur_dispbuf->type + & VIDTYPE_VIU_FIELD) { + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_ + >> 1; + zoom_end_y = + ((cur_frame_par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } else { + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_; + zoom_end_y = + cur_frame_par->VPP_vd_end_lines_; + } + } else { + if (cur_dispbuf->type & VIDTYPE_VIU_FIELD) { + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_; + zoom_end_y = + cur_frame_par->VPP_vd_end_lines_; + } else { + if (is_need_framepacking_output()) { + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_ >> 1; + zoom_end_y = + ((cur_frame_par->VPP_vd_end_lines_ + - framepacking_blank + 1) >> 1) - 1; + } else { + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_ >> 1; + zoom_end_y = + ((cur_frame_par->VPP_vd_end_lines_ + 1) >> 1) - 1; + } + } + } + + zoom_start_x_lines = + cur_frame_par->VPP_hd_start_lines_; + zoom_end_x_lines = cur_frame_par->VPP_hd_end_lines_; + zoom_display_horz(cur_dispbuf, + cur_frame_par->hscale_skip_count); + + zoom_start_y_lines = zoom_start_y; + zoom_end_y_lines = zoom_end_y; + zoom_display_vert(cur_dispbuf); + if (is_dolby_vision_enable() && cur_dispbuf2) { + zoom2_start_x_lines = ori2_start_x_lines; + zoom2_end_x_lines = ori2_end_x_lines; + zoom2_start_y_lines = ori2_start_y_lines; + zoom2_end_y_lines = ori2_end_y_lines; + correct_vd2_mif_size_for_DV( + cur_frame_par, cur_dispbuf); + vd2_zoom_display_horz(cur_dispbuf2, + cur_frame_par->hscale_skip_count); + vd2_zoom_display_vert(cur_dispbuf2, + cur_frame_par->vscale_skip_count); + } + } + /*vpp input size setting*/ + VSYNC_WR_MPEG_REG(VPP_IN_H_V_SIZE, + ((cur_frame_par->video_input_w & 0x1fff) << + 16) | (cur_frame_par->video_input_h & 0x1fff)); + + /* vpp super scaler */ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + vpp_set_super_scaler_regs(cur_frame_par->supscl_path, + cur_frame_par->supsc0_enable, + cur_frame_par->spsc0_w_in, + cur_frame_par->spsc0_h_in, + cur_frame_par->supsc0_hori_ratio, + cur_frame_par->supsc0_vert_ratio, + cur_frame_par->supsc1_enable, + cur_frame_par->spsc1_w_in, + cur_frame_par->spsc1_h_in, + cur_frame_par->supsc1_hori_ratio, + cur_frame_par->supsc1_vert_ratio, + vinfo->width, + vinfo->height); + if (is_dolby_vision_on() && + is_dolby_vision_stb_mode() && + !cur_frame_par->supsc0_enable && + !cur_frame_par->supsc1_enable) { + VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0); + VSYNC_WR_MPEG_REG(VPP_SRSHARP1_CTRL, 0); + } + } + + /* vpp filters */ + /* SET_MPEG_REG_MASK(VPP_SC_MISC + cur_dev->vpp_off, */ + /* VPP_SC_TOP_EN | VPP_SC_VERT_EN | VPP_SC_HORZ_EN); */ +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (for_dolby_vision_certification()) { + /* turn off PPS for Dolby Vision certification */ + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + 0, VPP_SC_TOP_EN_BIT, VPP_SC_TOP_EN_WID); + } else +#endif + { + VSYNC_WR_MPEG_REG(VPP_SC_MISC + cur_dev->vpp_off, + READ_VCBUS_REG(VPP_SC_MISC + + cur_dev->vpp_off) | + VPP_SC_TOP_EN | VPP_SC_VERT_EN | + VPP_SC_HORZ_EN); + + /* pps pre hsc&vsc en */ + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_pre_hsc_en, + VPP_SC_PREHORZ_EN_BIT, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_pre_vsc_en, + VPP_SC_PREVERT_EN_BIT, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_pre_vsc_en, + VPP_LINE_BUFFER_EN_BIT, 1); + } + /* for bypass pps debug */ + 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 && + bypass_pps) + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + 0, VPP_SC_TOP_EN_BIT, VPP_SC_TOP_EN_WID); + /*turn off vertical scaler when 3d display */ + /* CLEAR_MPEG_REG_MASK(VPP_SC_MISC,VPP_SC_VERT_EN); */ + if (platform_type == 1) { + if (last_mode_3d) { + VSYNC_WR_MPEG_REG( + VPP_SC_MISC + cur_dev->vpp_off, + READ_MPEG_REG(VPP_SC_MISC + + cur_dev->vpp_off) & + (~VPP_SC_VERT_EN)); + } + } + /* horitontal filter settings */ + VSYNC_WR_MPEG_REG_BITS( + VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_horz_coeff[0], + VPP_SC_HBANK_LENGTH_BIT, + VPP_SC_BANK_LENGTH_WID); + + /* fix the pps last line dummy issue */ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) + VSYNC_WR_MPEG_REG_BITS( + VPP_SC_MISC + cur_dev->vpp_off, + 1, 24, 1); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + && !is_meson_mtvd_cpu()) { + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + cur_dev->vpp_off, + (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); + } + /* #endif */ + + if (vpp_filter->vpp_horz_coeff[1] & 0x8000) { + VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + + cur_dev->vpp_off, + VPP_COEF_HORZ | VPP_COEF_9BIT); + } else { + VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + + cur_dev->vpp_off, + VPP_COEF_HORZ); + } + + for (i = 0; i < (vpp_filter->vpp_horz_coeff[1] & 0xff); i++) { + VSYNC_WR_MPEG_REG(VPP_SCALE_COEF + cur_dev->vpp_off, + vpp_filter->vpp_horz_coeff[i + 2]); + } + + /* vertical filter settings */ + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_vert_coeff[0], + VPP_SC_VBANK_LENGTH_BIT, + VPP_SC_BANK_LENGTH_WID); + + VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + cur_dev->vpp_off, + VPP_COEF_VERT); + for (i = 0; i < vpp_filter->vpp_vert_coeff[1]; i++) { + VSYNC_WR_MPEG_REG(VPP_SCALE_COEF + cur_dev->vpp_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; + + VSYNC_WR_MPEG_REG( + VPP_SCALE_COEF_IDX + cur_dev->vpp_off, + VPP_COEF_VERT_CHROMA|VPP_COEF_SEP_EN); + for (i = 0; i < pCoeff[1]; i++) + VSYNC_WR_MPEG_REG( + VPP_SCALE_COEF + cur_dev->vpp_off, + pCoeff[i + 2]); + } + /* work around to cut the last green line + *when two layer dv display and do vskip + */ + if (is_dolby_vision_on() && + (cur_frame_par->vscale_skip_count > 0) + && cur_dispbuf2 + && (cur_frame_par->VPP_pic_in_height_ > 0)) + cur_frame_par->VPP_pic_in_height_--; + VSYNC_WR_MPEG_REG(VPP_PIC_IN_HEIGHT + cur_dev->vpp_off, + cur_frame_par->VPP_pic_in_height_); + + VSYNC_WR_MPEG_REG_BITS(VPP_HSC_PHASE_CTRL + cur_dev->vpp_off, + cur_frame_par->VPP_hf_ini_phase_, + VPP_HSC_TOP_INI_PHASE_BIT, + VPP_HSC_TOP_INI_PHASE_WID); + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + cur_dev->vpp_off, + ((cur_frame_par->VPP_post_blend_vd_h_start_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + ((cur_frame_par->VPP_post_blend_vd_h_end_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END + + cur_dev->vpp_off, + ((cur_frame_par->VPP_post_blend_vd_v_start_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + ((cur_frame_par->VPP_post_blend_vd_v_end_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + + if ((cur_frame_par->VPP_post_blend_vd_v_end_ - + cur_frame_par->VPP_post_blend_vd_v_start_ + 1) > 1080) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + cur_dev->vpp_off, + ((cur_frame_par->VPP_post_blend_vd_v_start_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + ((cur_frame_par->VPP_post_blend_vd_v_end_ & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } else { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + cur_dev->vpp_off, + ((0 & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | ((1079 & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } + + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VPP_PREBLEND_H_SIZE + cur_dev->vpp_off, + (cur_frame_par->video_input_h << 16) + | cur_frame_par->video_input_w); + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off, + ((cur_frame_par->VPP_post_blend_vd_v_end_ + 1) + << 16) | + cur_frame_par->VPP_post_blend_h_size_); + } else { + VSYNC_WR_MPEG_REG( + VPP_PREBLEND_H_SIZE + cur_dev->vpp_off, + cur_frame_par->VPP_line_in_length_); + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off, + cur_frame_par->VPP_post_blend_h_size_); + } + + vpp_settings_h(cur_frame_par); + vpp_settings_v(cur_frame_par); + if (is_dolby_vision_enable() && cur_dispbuf2) { + vd2_settings_h(cur_dispbuf2); + vd2_settings_v(cur_dispbuf2); + } + frame_par_ready_to_set = 0; + frame_par_force_to_set = 0; + first_set = 1; + } + /* VPP one time settings */ + wait_sync = 0; + + if (!legacy_vpp && vinfo) { + u32 read_value = VSYNC_RD_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off); + if (((vinfo->field_height << 16) | vinfo->width) + != read_value) + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off, + ((vinfo->field_height << 16) | vinfo->width)); + } else if (vinfo) { + if (VSYNC_RD_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off) + != vinfo->width) + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off, + vinfo->width); + } + + if (cur_dispbuf && cur_dispbuf->process_fun) { + /* for new deinterlace driver */ +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { + if (enable_rdma_log_count > 0) + pr_info("call process_fun\n"); + } +#endif + cur_dispbuf->process_fun(cur_dispbuf->private_data, + zoom_start_x_lines | + (cur_frame_par->vscale_skip_count << + 24) | (frame_par_di_set << 16), + zoom_end_x_lines, zoom_start_y_lines, + zoom_end_y_lines, cur_dispbuf); + } + + exit: +#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) + pts_trace++; +#endif + vpp_misc_save = READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off); + vpp_misc_set = vpp_misc_save; +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM + if (!is_dolby_vision_on()) + vpp_misc_set |= VPP_CM_ENABLE; + else + vpp_misc_set &= ~VPP_CM_ENABLE; +#endif + + if (bypass_cm) + 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; + } + +#ifdef VIDEO_PIP + if (cur_pipbuf && (video2_enabled == 1) + && ((vpp_misc_save & VPP_VD2_POSTBLEND) == 0) + && (video2_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { + vpp_misc_set |= + VPP_VD2_POSTBLEND | + VPP_POSTBLEND_EN; + } +#endif + + if ((video_enabled == 1) && ((vpp_misc_save & VPP_VD1_POSTBLEND) == 0) + && (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { + vpp_misc_set |= + VPP_VD1_PREBLEND | + VPP_VD1_POSTBLEND | + VPP_POSTBLEND_EN; + } + if ((video_enabled == 1) && cur_frame_par + && (cur_dispbuf != &vf_local) && (first_set == 0) + && (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { + 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 + cur_dev->vpp_off); + v_phase_step = READ_VCBUS_REG( + VPP_VSC_START_PHASE_STEP + cur_dev->vpp_off); + if ((vpp_filter->vpp_hf_start_phase_step != h_phase_step) || + (vpp_filter->vpp_vsc_start_phase_step != v_phase_step)) { + video_property_changed = 1; + /*pr_info("frame info register rdma write fail!\n");*/ + } + } + if (likely(video_onoff_state != VIDEO_ENABLE_STATE_IDLE)) { + /* state change for video layer enable/disable */ + + spin_lock_irqsave(&video_onoff_lock, flags); + + if (video_onoff_state == VIDEO_ENABLE_STATE_ON_REQ) { + /* + * the video layer is enabled one vsync later,assumming + * all registers are ready from RDMA. + */ + video_onoff_state = VIDEO_ENABLE_STATE_ON_PENDING; + } else if (video_onoff_state == + VIDEO_ENABLE_STATE_ON_PENDING) { + vpp_misc_set |= VPP_VD1_PREBLEND | + VPP_VD1_POSTBLEND | + VPP_POSTBLEND_EN; + + video_onoff_state = VIDEO_ENABLE_STATE_IDLE; + video_onoff_time = jiffies_to_msecs(jiffies); + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("VsyncEnableVideoLayer\n"); + vpu_delay_work_flag |= + VPU_VIDEO_LAYER1_CHANGED; + force_flush = 1; + } else if (video_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { + vpp_misc_set &= ~(VPP_VD1_PREBLEND | + VPP_VD1_POSTBLEND); + if (process_3d_type) + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); + /*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); + } + video_onoff_state = VIDEO_ENABLE_STATE_IDLE; + video_onoff_time = jiffies_to_msecs(jiffies); + vpu_delay_work_flag |= + VPU_VIDEO_LAYER1_CHANGED; + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("VsyncDisableVideoLayer\n"); + video1_off_req = 1; + force_flush = 1; + } + + spin_unlock_irqrestore(&video_onoff_lock, flags); + } + + if (likely(video2_onoff_state != VIDEO_ENABLE_STATE_IDLE)) { + /* state change for video layer2 enable/disable */ + + spin_lock_irqsave(&video2_onoff_lock, flags); + + if (video2_onoff_state == VIDEO_ENABLE_STATE_ON_REQ) { + /* + * the video layer 2 + * is enabled one vsync later, assumming + * all registers are ready from RDMA. + */ + video2_onoff_state = VIDEO_ENABLE_STATE_ON_PENDING; + } else if (video2_onoff_state == + VIDEO_ENABLE_STATE_ON_PENDING) { + if (is_dolby_vision_on()) + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); + else if (process_3d_type || + (cur_dispbuf && + (cur_dispbuf->type & VIDTYPE_MVC))) + vpp_misc_set |= VPP_VD2_PREBLEND | + VPP_PREBLEND_EN; + else if (!legacy_vpp) + vpp_misc_set |= VPP_VD2_POSTBLEND | + VPP_POSTBLEND_EN; + else + vpp_misc_set |= VPP_VD2_PREBLEND | + VPP_PREBLEND_EN; +#ifdef VIDEO_PIP + if (cur_pipbuf) { + vpp_misc_set &= + ~(VPP_PREBLEND_EN | VPP_VD2_PREBLEND); + vpp_misc_set |= VPP_VD2_POSTBLEND; + } +#endif + /* g12a has no alpha overflow check in hardware */ + if (!legacy_vpp) + vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT); + else + vpp_misc_set |= (0x1ff << VPP_VD2_ALPHA_BIT); + video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; + video_onoff_time = jiffies_to_msecs(jiffies); + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("VsyncEnableVideoLayer2\n"); + force_flush = 1; + } else if (video2_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND | VPP_PREBLEND_EN + | (0x1ff << VPP_VD2_ALPHA_BIT)); + video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; + video_onoff_time = jiffies_to_msecs(jiffies); + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("VsyncDisableVideoLayer2\n"); + video2_off_req = 1; + force_flush = 1; + } + spin_unlock_irqrestore(&video2_onoff_lock, flags); + } + + if ((video_global_output == 0) + || black_threshold_check(0)) { + video_enabled = 0; + vpp_misc_set &= ~(VPP_VD1_PREBLEND | + VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND | + VPP_VD1_POSTBLEND | + VPP_PREBLEND_EN); +#ifdef VIDEO_PIP + /* should keep video2 display */ + if (cur_pipbuf && video2_enabled) + vpp_misc_set |= VPP_VD2_POSTBLEND; +#endif + } else { + video_enabled = video_status_saved; + } + + if (!video_enabled && + (vpp_misc_set & VPP_VD1_POSTBLEND)) + vpp_misc_set &= ~(VPP_VD1_PREBLEND | + VPP_VD1_POSTBLEND | + VPP_PREBLEND_EN); + +#ifdef VIDEO_PIP + if ((pip_global_output == 0) + || black_threshold_check(1)) { + video2_enabled = 0; + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND); + } else { + video2_enabled = video2_status_saved; + } + + if (!video2_enabled && + (vpp_misc_set & VPP_VD2_POSTBLEND)) + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND); +#endif + + if (!legacy_vpp) { + u32 set_value = 0; + + force_flush |= vpp_zorder_check(); + + /* for sr core0, put it between prebld & pps as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE0_SUPPORT)) + if (cur_frame_par->sr0_position) + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + else + vpp_misc_set &= + ~SR0_AFTER_DNLP; + else + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + /* for sr core1, put it before post blend as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE1_SUPPORT)) + if (cur_frame_par->sr1_position) + vpp_misc_set |= + DNLP_SR1_CM; + else + vpp_misc_set &= + ~SR1_AFTER_POSTBLEN; + 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 */ + if (((vpp_misc_set & VPP_VD1_POSTBLEND) == 0) + && (vpp_misc_set & VPP_VD2_POSTBLEND)) { + vpp_misc_set &= ~(0x1ff << VPP_VD2_ALPHA_BIT); + vpp_misc_set |= (0x100 << 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] + + cur_dev->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 (bypass_cm) + set_value &= ~VPP_CM_ENABLE; + set_value |= VPP_POSTBLEND_EN; + VSYNC_WR_MPEG_REG( + VPP_MISC + cur_dev->vpp_off, + set_value); + } + } else if (vpp_misc_save != vpp_misc_set) + VSYNC_WR_MPEG_REG( + VPP_MISC + cur_dev->vpp_off, + vpp_misc_set); + + /*vpp_misc_set maybe have same,but need off.*/ + /* if vd1 off, disable vd2 also */ +#ifdef VIDEO_PIP + if (video2_off_req && cur_pipbuf) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + if (cur_pipbuf && (cur_pipbuf == &local_pip)) + cur_pipbuf = NULL; + } else if (!cur_pipbuf && + (video2_off_req || video1_off_req)) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + last_el_w = 0; + last_el_status = 0; + if (cur_dispbuf2 && (cur_dispbuf2 == &vf_local2)) + cur_dispbuf2 = NULL; + need_disable_vd2 = false; + } +#else + if (video2_off_req || video1_off_req) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_GEN_REG + cur_dev->viu_off, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + last_el_w = 0; + last_el_status = 0; + if (cur_dispbuf2 && (cur_dispbuf2 == &vf_local2)) + cur_dispbuf2 = NULL; + need_disable_vd2 = false; + } +#endif + + if (video1_off_req) { + /* + * video layer off, switch off afbc, + * will enabled on new frame coming. + */ + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("AFBC off now.\n"); + VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG( + VD1_IF0_GEN_REG + cur_dev->viu_off, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + if (is_dolby_vision_enable()) { + #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) + if (is_meson_txlx_stbmode() || + is_meson_gxm()) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 1, 16, 1); /* bypass core1 */ + else + #endif + if (cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, 1, 0, 1); + } + if (cur_dispbuf && (cur_dispbuf == &vf_local)) + cur_dispbuf = NULL; + } +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + cur_rdma_buf = cur_dispbuf; +#ifdef VIDEO_PIP + pip_rdma_buf = cur_pipbuf; +#endif + /* vsync_rdma_config(); */ + vsync_rdma_process(); + if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { + if (enable_rdma_log_count == 0) + enable_rdma_log(0); + } + rdma_enable_pre = is_vsync_rdma_enable(); +#endif + + if (timer_count > 50) { + timer_count = 0; + video_notify_flag |= VIDEO_NOTIFY_FRAME_WAIT; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + if ((video_scaler_mode) && (scaler_pos_changed)) { + video_notify_flag |= VIDEO_NOTIFY_POS_CHANGED; + scaler_pos_changed = 0; + } else { + scaler_pos_changed = 0; + video_notify_flag &= ~VIDEO_NOTIFY_POS_CHANGED; + } +#endif + } + + switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) { + case 0: + enc_line = (READ_VCBUS_REG(ENCL_INFO_READ) >> 16) & 0x1fff; + break; + case 1: + enc_line = (READ_VCBUS_REG(ENCI_INFO_READ) >> 16) & 0x1fff; + break; + case 2: + enc_line = (READ_VCBUS_REG(ENCP_INFO_READ) >> 16) & 0x1fff; + break; + case 3: + enc_line = (READ_VCBUS_REG(ENCT_INFO_READ) >> 16) & 0x1fff; + break; + } + if (enc_line > vsync_exit_line_max) + vsync_exit_line_max = enc_line; + +#ifdef FIQ_VSYNC + if (video_notify_flag) + fiq_bridge_pulse_trigger(&vsync_fiq_bridge); +#else + if (video_notify_flag) + vsync_notify(); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { + if (vpu_delay_work_flag) + schedule_work(&vpu_delay_work); + } + /* #endif */ + + return IRQ_HANDLED; +#endif + +} + + +#ifdef FIQ_VSYNC +void vsync_fisr(void) +{ + atomic_set(&video_inirq_flag, 1); + vsync_fisr_in(); + atomic_set(&video_inirq_flag, 0); +} +#else +static irqreturn_t vsync_isr(int irq, void *dev_id) +{ + irqreturn_t ret; + + atomic_set(&video_inirq_flag, 1); + ret = vsync_isr_in(irq, dev_id); + atomic_set(&video_inirq_flag, 0); + return ret; +} +#endif + + +/********************************************************* + * FIQ Routines + *********************************************************/ + +static void vsync_fiq_up(void) +{ +#ifdef FIQ_VSYNC + request_fiq(INT_VIU_VSYNC, &vsync_fisr); +#else + int r; + /*TODO irq */ + r = request_irq(video_vsync, &vsync_isr, + IRQF_SHARED, "vsync", (void *)video_dev_id); + +#ifdef CONFIG_MESON_TRUSTZONE + if (num_online_cpus() > 1) + irq_set_affinity(INT_VIU_VSYNC, cpumask_of(1)); +#endif +#endif +} + +static void vsync_fiq_down(void) +{ +#ifdef FIQ_VSYNC + free_fiq(INT_VIU_VSYNC, &vsync_fisr); +#else + /*TODO irq */ + free_irq(video_vsync, (void *)video_dev_id); +#endif +} + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 +static void vsync2_fiq_up(void) +{ + int r; + + r = request_irq(INT_VIU2_VSYNC, &vsync_isr, + IRQF_SHARED, "vsync", (void *)video_dev_id2); +} + +static void vsync2_fiq_down(void) +{ + free_irq(INT_VIU2_VSYNC, (void *)video_dev_id2); +} + +#endif + +int get_curren_frame_para(int *top, int *left, int *bottom, int *right) +{ + if (!cur_frame_par) + return -1; + *top = cur_frame_par->VPP_vd_start_lines_; + *left = cur_frame_par->VPP_hd_start_lines_; + *bottom = cur_frame_par->VPP_vd_end_lines_; + *right = cur_frame_par->VPP_hd_end_lines_; + return 0; +} + +int get_current_vscale_skip_count(struct vframe_s *vf) +{ + int ret = 0; + static struct vpp_frame_par_s frame_par; + + vpp_set_filters( + &glayer_info[0], + vf, &frame_par, vinfo, + (is_dolby_vision_on() && + is_dolby_vision_stb_mode()), 0); + ret = frame_par.vscale_skip_count; + if (cur_frame_par && (process_3d_type & MODE_3D_ENABLE)) + ret |= (cur_frame_par->vpp_3d_mode<<8); + return ret; +} + +int query_video_status(int type, int *value) +{ + if (value == NULL) + return -1; + switch (type) { + case 0: + *value = trickmode_fffb; + break; + case 1: + *value = trickmode_i; + break; + default: + break; + } + return 0; +} +EXPORT_SYMBOL(query_video_status); + +static void video_vf_unreg_provider(void) +{ + ulong flags; + struct vframe_s *el_vf = NULL; + int keeped = 0; + + new_frame_count = 0; + first_frame_toggled = 0; + videopeek = 0; + nopostvideostart = false; + + atomic_set(&video_unreg_flag, 1); + while (atomic_read(&video_inirq_flag) > 0) + schedule(); + memset(&video_frame_detect, 0, + sizeof(struct video_frame_detect_s)); + frame_detect_drop_count = 0; + frame_detect_receive_count = 0; + spin_lock_irqsave(&lock, flags); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + dispbuf_to_put_num = DISPBUF_TO_PUT_MAX; + while (dispbuf_to_put_num > 0) { + dispbuf_to_put_num--; + dispbuf_to_put[dispbuf_to_put_num] = NULL; + } + cur_rdma_buf = NULL; +#endif + if (cur_dispbuf) { + vf_local = *cur_dispbuf; + cur_dispbuf = &vf_local; + cur_dispbuf->video_angle = 0; + } + if (cur_dispbuf2) + need_disable_vd2 = true; + if (is_dolby_vision_enable()) { + if (cur_dispbuf2 == &vf_local2) + cur_dispbuf2 = NULL; + else if (cur_dispbuf2 != NULL) { + vf_local2 = *cur_dispbuf2; + el_vf = &vf_local2; + } + cur_dispbuf2 = NULL; + } + if (trickmode_fffb) { + atomic_set(&trickmode_framedone, 0); + to_notify_trick_wait = false; + } + + vsync_pts_100 = 0; + vsync_pts_112 = 0; + vsync_pts_125 = 0; + vsync_freerun = 0; + vsync_pts_align = 0; + vsync_pts_aligned = false; + +#ifdef VIDEO_PIP + if (pip_loop) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + cur_pipbuf->video_angle = 0; + } + pip_frame_count = 0; + } +#endif + spin_unlock_irqrestore(&lock, flags); + +#ifdef VIDEO_PIP + if (pip_loop) { + disable_videopip = VIDEO_DISABLE_FORNEXT; + DisableVideoLayer2(); + } +#endif + + if (blackout | force_blackout) { + safe_disable_videolayer(); + try_free_keep_video(1); + } + +#ifdef CONFIG_GE2D_KEEP_FRAME + if (cur_dispbuf) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("ge2d", 1); */ + keeped = vf_keep_current(cur_dispbuf, el_vf); + /* TODO: mod gate */ + /* switch_mod_gate_by_name("ge2d", 0); */ + } + if ((hdmi_in_onvideo == 0) && (video_start_post)) { + tsync_avevent(VIDEO_STOP, 0); + video_start_post = false; + } +#else + /* if (!trickmode_fffb) */ + if (cur_dispbuf) + keeped = vf_keep_current(cur_dispbuf, el_vf); + if ((hdmi_in_onvideo == 0) && (video_start_post)) { + tsync_avevent(VIDEO_STOP, 0); + video_start_post = false; + } +#endif + if (keeped < 0) {/*keep failed.*/ + pr_info("video keep failed, disable video now!\n"); + safe_disable_videolayer(); + try_free_keep_video(1); + } + atomic_set(&video_unreg_flag, 0); + pr_info("VD1 AFBC 0x%x.\n", READ_VCBUS_REG(AFBC_ENABLE)); + enable_video_discontinue_report = 1; + show_first_picture = false; + show_first_frame_nosync = false; + + time_setomxpts.tv_sec = 0; + time_setomxpts.tv_usec = 0; + +#ifdef PTS_LOGGING + { + int pattern; + /* Print what we have right now*/ + if (pts_pattern_detected >= PTS_32_PATTERN && + pts_pattern_detected < PTS_MAX_NUM_PATTERNS) { + pr_info("pattern detected = %d, pts_enter_pattern_cnt =%d, pts_exit_pattern_cnt =%d", + pts_pattern_detected, + pts_pattern_enter_cnt[pts_pattern_detected], + pts_pattern_exit_cnt[pts_pattern_detected]); + } + /* Reset all metrics now*/ + for (pattern = 0; pattern < PTS_MAX_NUM_PATTERNS; pattern++) { + pts_pattern[pattern] = 0; + pts_pattern_exit_cnt[pattern] = 0; + pts_pattern_enter_cnt[pattern] = 0; + } + /* Reset 4:1 data*/ + memset(&pts_41_pattern_sink[0], 0, PTS_41_PATTERN_SINK_MAX); + pts_pattern_detected = -1; + pre_pts_trace = 0; + pts_escape_vsync = 0; + } +#endif +} + +static void video_vf_light_unreg_provider(int need_keep_frame) +{ + ulong flags; + + if (need_keep_frame) { + /* wait for the end of the last toggled frame*/ + atomic_set(&video_unreg_flag, 1); + while (atomic_read(&video_inirq_flag) > 0) + schedule(); + } + + spin_lock_irqsave(&lock, flags); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + dispbuf_to_put_num = DISPBUF_TO_PUT_MAX; + while (dispbuf_to_put_num > 0) { + dispbuf_to_put_num--; + dispbuf_to_put[dispbuf_to_put_num] = NULL; + } + cur_rdma_buf = NULL; +#endif + + if (cur_dispbuf) { + vf_local = *cur_dispbuf; + cur_dispbuf = &vf_local; + } + spin_unlock_irqrestore(&lock, flags); + + if (need_keep_frame) { + /* keep the last toggled frame*/ + if (cur_dispbuf) { + unsigned int result; + + result = vf_keep_current(cur_dispbuf, NULL); + if (result == 0) + pr_info("%s: keep cur_disbuf failed\n", + __func__); + } + atomic_set(&video_unreg_flag, 0); + } +} + +static int get_display_info(void *data) +{ + s32 w, h, x, y; + struct vdisplay_info_s *info_para = (struct vdisplay_info_s *)data; + const struct vinfo_s *info = get_current_vinfo(); + struct disp_info_s *layer = &glayer_info[0]; + + if ((!cur_frame_par) || (!info)) + return -1; + + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; + + if ((w == 0) || (w > info->width)) + w = info->width; + if ((h == 0) || (h > info->height)) + h = info->height; + + info_para->frame_hd_start_lines_ = cur_frame_par->VPP_hd_start_lines_; + info_para->frame_hd_end_lines_ = cur_frame_par->VPP_hd_end_lines_; + info_para->frame_vd_start_lines_ = cur_frame_par->VPP_vd_start_lines_; + info_para->frame_vd_end_lines_ = cur_frame_par->VPP_vd_end_lines_; + info_para->display_hsc_startp = cur_frame_par->VPP_hsc_startp - x; + info_para->display_hsc_endp = + cur_frame_par->VPP_hsc_endp + (info->width - x - w); + info_para->display_vsc_startp = cur_frame_par->VPP_vsc_startp - y; + info_para->display_vsc_endp = + cur_frame_par->VPP_vsc_endp + (info->height - y - h); + info_para->screen_vd_h_start_ = + cur_frame_par->VPP_post_blend_vd_h_start_; + info_para->screen_vd_h_end_ = + cur_frame_par->VPP_post_blend_vd_h_end_; + info_para->screen_vd_v_start_ = + cur_frame_par->VPP_post_blend_vd_v_start_; + info_para->screen_vd_v_end_ = cur_frame_par->VPP_post_blend_vd_v_end_; + + return 0; +} +#if ENABLE_UPDATE_HDR_FROM_USER +void init_hdr_info(void) +{ + unsigned long flags; + + spin_lock_irqsave(&omx_hdr_lock, flags); + + has_hdr_info = false; + memset(&vf_hdr, 0, sizeof(vf_hdr)); + + spin_unlock_irqrestore(&omx_hdr_lock, flags); +} +#endif +static int video_receiver_event_fun(int type, void *data, void *private_data) +{ +#ifdef CONFIG_AM_VIDEO2 + char *provider_name; +#endif + if (type == VFRAME_EVENT_PROVIDER_UNREG) { + video_vf_unreg_provider(); +#ifdef CONFIG_AM_VIDEO2 + set_clone_frame_rate(android_clone_rate, 200); +#endif + drop_frame_count = 0; + receive_frame_count = 0; + display_frame_count = 0; + //init_hdr_info(); + + } else if (type == VFRAME_EVENT_PROVIDER_RESET) { + video_vf_light_unreg_provider(1); + } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) + video_vf_light_unreg_provider(0); + else if (type == VFRAME_EVENT_PROVIDER_REG) { + enable_video_discontinue_report = 1; + drop_frame_count = 0; + receive_frame_count = 0; + display_frame_count = 0; + omx_run = false; + omx_pts_set_from_hwc_count = 0; + omx_check_previous_session = true; + omx_need_drop_frame_num = 0; + omx_drop_done = false; + omx_pts_set_index = 0; + //init_hdr_info(); + +#ifdef CONFIG_AM_VIDEO2 + provider_name = (char *)data; + if (strncmp(provider_name, "decoder", 7) == 0 + || strncmp(provider_name, "ppmgr", 5) == 0 + || strncmp(provider_name, "deinterlace", 11) == 0 + || strncmp(provider_name, "d2d3", 11) == 0) { + set_clone_frame_rate(noneseamless_play_clone_rate, 0); + set_clone_frame_rate(video_play_clone_rate, 100); + } +#endif +/*notify di 3d mode is frame*/ +/*alternative mode,passing two buffer in one frame */ + if (platform_type == 1) { + if ((process_3d_type & MODE_3D_FA) + #if defined(CONFIG_AMLOGIC_MEDIA_TVIN) + && !cur_dispbuf->trans_fmt + #endif + ) + vf_notify_receiver_by_name("deinterlace", + VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE, + (void *)1); + } + + video_vf_light_unreg_provider(0); + } else if (type == VFRAME_EVENT_PROVIDER_FORCE_BLACKOUT) { + force_blackout = 1; + if (debug_flag & DEBUG_FLAG_BLACKOUT) { + pr_info("%s VFRAME_EVENT_PROVIDER_FORCE_BLACKOUT\n", + __func__); + } + } else if (type == VFRAME_EVENT_PROVIDER_FR_HINT) { +#ifdef CONFIG_AM_VOUT + if ((data != NULL) && (video_seek_flag == 0)) { + set_vframe_rate_hint((unsigned long)data); + omx_pts_dv_upper = DUR2PTS((unsigned long)data) * 3 / 2; + omx_pts_dv_lower = 0 - DUR2PTS((unsigned long)data); + } +#endif + } else if (type == VFRAME_EVENT_PROVIDER_FR_END_HINT) { +#ifdef CONFIG_AM_VOUT + if (video_seek_flag == 0) { + set_vframe_rate_end_hint(); + omx_pts_dv_upper = OMX_PTS_DV_DEFAULT_UPPER; + omx_pts_dv_lower = OMX_PTS_DV_DEFAULT_LOWER; + } +#endif + } else if (type == VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO) { + get_display_info(data); + } else if (type == VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED) + video_property_changed = 1; + return 0; +} + +#ifdef VIDEO_PIP +static void pip_vf_unreg_provider(void) +{ + ulong flags; + int keeped = 0; + + /* atomic_set(&video_unreg_flag, 1); */ + while (atomic_read(&video_inirq_flag) > 0) + schedule(); + spin_lock_irqsave(&lock, flags); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + cur_pipbuf->video_angle = 0; + } + pip_frame_count = 0; + spin_unlock_irqrestore(&lock, flags); + + if (blackout_pip | force_blackout) { + safe_disable_videolayer2(); + try_free_keep_videopip(1); + } + + if (cur_pipbuf) + keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL); + + if (keeped < 0) {/*keep failed.*/ + pr_info("videopip keep failed, disable video now!\n"); + safe_disable_videolayer2(); + try_free_keep_videopip(1); + } + + /*disable_videopip = VIDEO_DISABLE_FORNEXT;*/ + /*DisableVideoLayer2();*/ +} + +static void pip_vf_light_unreg_provider(int need_keep_frame) +{ + ulong flags; + + spin_lock_irqsave(&lock, flags); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + } + spin_unlock_irqrestore(&lock, flags); + if (need_keep_frame) { + if (cur_pipbuf) + vf_keep_pip_current_locked(cur_pipbuf, NULL); + } +} + +static int pip_receiver_event_fun( + int type, void *data, void *private_data) +{ + if (type == VFRAME_EVENT_PROVIDER_UNREG) + pip_vf_unreg_provider(); + else if (type == VFRAME_EVENT_PROVIDER_RESET) + pip_vf_light_unreg_provider(1); + else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) + pip_vf_light_unreg_provider(0); + else if (type == VFRAME_EVENT_PROVIDER_REG) + pip_vf_light_unreg_provider(0); + return 0; +} +#endif + +unsigned int get_post_canvas(void) +{ + return post_canvas; +} +EXPORT_SYMBOL(get_post_canvas); + + +u32 get_blackout_policy(void) +{ + return blackout | force_blackout; +} +EXPORT_SYMBOL(get_blackout_policy); + +u32 set_blackout_policy(int policy) +{ + blackout = policy; + return 0; +} +EXPORT_SYMBOL(set_blackout_policy); + +u32 get_blackout_pip_policy(void) +{ + return blackout_pip | force_blackout; +} +EXPORT_SYMBOL(get_blackout_pip_policy); + +u32 set_blackout_pip_policy(int policy) +{ + blackout_pip = policy; + return 0; +} +EXPORT_SYMBOL(set_blackout_pip_policy); + +u8 is_vpp_postblend(void) +{ + if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_VD1_POSTBLEND) + return 1; + return 0; +} +EXPORT_SYMBOL(is_vpp_postblend); + +void pause_video(unsigned char pause_flag) +{ + atomic_set(&video_pause_flag, pause_flag ? 1 : 0); +} +EXPORT_SYMBOL(pause_video); +/********************************************************* + * Utilities + *********************************************************/ +int _video_set_disable(u32 val) +{ + if (val > VIDEO_DISABLE_FORNEXT) + return -EINVAL; + + disable_video = val; + + if (disable_video != VIDEO_DISABLE_NONE) { + safe_disable_videolayer(); + + if ((disable_video == VIDEO_DISABLE_FORNEXT) && cur_dispbuf + && (cur_dispbuf != &vf_local)) + video_property_changed = 1; + try_free_keep_video(0); + } else { + if (cur_dispbuf && (cur_dispbuf != &vf_local)) { + EnableVideoLayer(); + video_property_changed = 1; + } + } + + return 0; +} + +static void _set_video_crop( + struct disp_info_s *layer, int *p) +{ + int last_l, last_r, last_t, last_b; + int new_l, new_r, new_t, new_b; + + if (!layer) + return; + + last_t = layer->crop_top; + last_l = layer->crop_left; + last_b = layer->crop_bottom; + last_r = layer->crop_right; + + new_t = layer->crop_top = p[0]; + new_l = layer->crop_left = p[1]; + new_b = layer->crop_bottom = p[2]; + new_r = layer->crop_right = p[3]; + if ((new_t != last_t) || (new_l != last_l) + || (new_b != last_b) || (new_r != last_r)) { + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif + } +} + +static void _set_video_window( + struct disp_info_s *layer, int *p) +{ + int w, h; + int *parsed = p; + int last_x, last_y, last_w, last_h; + int new_x, new_y, new_w, new_h; +#ifdef TV_REVERSE + int temp, temp1; + const struct vinfo_s *info = get_current_vinfo(); +#endif + + if (!layer) + return; + +#ifdef TV_REVERSE + /* FIXME: use layer info */ + if (reverse) { + temp = parsed[0]; + temp1 = parsed[1]; + parsed[0] = info->width - parsed[2] - 1; + parsed[1] = info->height - parsed[3] - 1; + parsed[2] = info->width - temp - 1; + parsed[3] = info->height - temp1 - 1; + } +#endif + + last_x = layer->layer_left; + last_y = layer->layer_top; + last_w = layer->layer_width; + last_h = layer->layer_height; + + if (parsed[0] < 0 && parsed[2] < 2) { + parsed[2] = 2; + parsed[0] = 0; + } + if (parsed[1] < 0 && parsed[3] < 2) { + parsed[3] = 2; + parsed[1] = 0; + } + w = parsed[2] - parsed[0] + 1; + h = parsed[3] - parsed[1] + 1; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + if (video_scaler_mode) { + if ((w == 1) && (h == 1)) { + w = 0; + h = 0; + } + if ((content_left != parsed[0]) || (content_top != parsed[1]) + || (content_w != w) || (content_h != h)) + scaler_pos_changed = 1; + content_left = parsed[0]; + content_top = parsed[1]; + content_w = w; + content_h = h; + /* video_notify_flag =*/ + /*video_notify_flag|VIDEO_NOTIFY_POS_CHANGED; */ + } else +#endif + { + if ((w > 0) && (h > 0)) { + if ((w == 1) && (h == 1)) { + w = 0; + h = 0; + } + layer->layer_left = parsed[0]; + layer->layer_top = parsed[1]; + layer->layer_width = w; + layer->layer_height = h; + } + } + + new_x = layer->layer_left; + new_y = layer->layer_top; + new_w = layer->layer_width; + new_h = layer->layer_height; + + if ((last_x != new_x) || (last_y != new_y) + || (last_w != new_w) || (last_h != new_h)) { + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif + } +} +#if ENABLE_UPDATE_HDR_FROM_USER +static void config_hdr_info(const struct vframe_master_display_colour_s p) +{ + struct vframe_master_display_colour_s tmp = {0}; + bool valid_hdr = false; + unsigned long flags; + + tmp.present_flag = p.present_flag; + if (tmp.present_flag == 1) { + tmp = p; + + if (tmp.primaries[0][0] == 0 && + tmp.primaries[0][1] == 0 && + tmp.primaries[1][0] == 0 && + tmp.primaries[1][1] == 0 && + tmp.primaries[2][0] == 0 && + tmp.primaries[2][1] == 0 && + tmp.white_point[0] == 0 && + tmp.white_point[1] == 0 && + tmp.luminance[0] == 0 && + tmp.luminance[1] == 0 && + tmp.content_light_level.max_content == 0 && + tmp.content_light_level.max_pic_average == 0) { + valid_hdr = false; + } else { + valid_hdr = true; + } + } + + spin_lock_irqsave(&omx_hdr_lock, flags); + vf_hdr = tmp; + has_hdr_info = valid_hdr; + spin_unlock_irqrestore(&omx_hdr_lock, flags); + + pr_debug("has_hdr_info %d\n", has_hdr_info); +} +#endif +static void set_omx_pts(u32 *p) +{ + u32 tmp_pts = p[0]; + /*u32 vision = p[1];*/ + u32 set_from_hwc = p[2]; + u32 frame_num = p[3]; + u32 not_reset = p[4]; + u32 session = p[5]; + unsigned int try_cnt = 0x1000; + + cur_omx_index = frame_num; + mutex_lock(&omx_mutex); + if (omx_pts_set_index < frame_num) + omx_pts_set_index = frame_num; + + if (omx_check_previous_session) { + if (session != omx_cur_session) { + omx_cur_session = session; + omx_check_previous_session = false; + } else { + mutex_unlock(&omx_mutex); + pr_info("check session return: tmp_pts %d session=0x%x\n", + tmp_pts, omx_cur_session); + return; + } + } + if (debug_flag & DEBUG_FLAG_PTS_TRACE) + pr_info("[%s]tmp_pts:%d, set_from_hwc:%d,frame_num=%d, not_reset=%d\n", + __func__, tmp_pts, set_from_hwc, frame_num, not_reset); + + if (not_reset == 0) { + omx_pts = tmp_pts; + ATRACE_COUNTER("omxpts", omx_pts); + do_gettimeofday(&time_setomxpts); + } + /* kodi may render first frame, then drop dozens of frames */ + if (set_from_hwc == 0 && omx_run == true && frame_num <= 2 + && not_reset == 0) { + pr_info("reset omx_run to false.\n"); + omx_run = false; + } + if (set_from_hwc == 1) { + if (!omx_run) { + omx_need_drop_frame_num = + frame_num > 0 ? frame_num-1 : 0; + if (omx_need_drop_frame_num == 0) + omx_drop_done = true; + pr_info("omx_need_drop_frame_num %d\n", + omx_need_drop_frame_num); + } + omx_run = true; + if (omx_pts_set_from_hwc_count < OMX_MAX_COUNT_RESET_SYSTEMTIME) + omx_pts_set_from_hwc_count++; + + } else if (set_from_hwc == 0 && !omx_run) { + struct vframe_s *vf = NULL; + u32 donot_drop = 0; + + while (try_cnt--) { + vf = vf_peek(RECEIVER_NAME); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (is_dolby_vision_enable() + && vf && is_dovi_frame(vf)) { + pr_info("%s ignore the omx %d frames drop for dv frame\n", + __func__, frame_num); + donot_drop = 1; + break; + } +#endif + if (vf) { + pr_debug("drop frame_num=%d, vf->omx_index=%d\n", + frame_num, vf->omx_index); + if (frame_num >= vf->omx_index) { + vf = vf_get(RECEIVER_NAME); + if (vf) + vf_put(vf, RECEIVER_NAME); + } else + break; + } else + break; + } + if (donot_drop && omx_pts_set_from_hwc_count > 0) { + pr_info("reset omx_run to true.\n"); + omx_run = true; + } + } + mutex_unlock(&omx_mutex); +} + +static int alloc_layer(u32 layer_id) +{ + int ret = -EINVAL; + + if (layer_id == 0) { + if (layer_cap & LAYER0_BUSY) { + ret = -EBUSY; + } else if (layer_cap & LAYER0_AVAIL) { + ret = 0; + layer_cap |= LAYER0_BUSY; + } + } else if (layer_id == 1) { + if (layer_cap & LAYER1_BUSY) { + ret = -EBUSY; + } else if (layer_cap & LAYER1_AVAIL) { + ret = 0; + layer_cap |= LAYER1_BUSY; + } + } + return ret; +} + +static int free_layer(u32 layer_id) +{ + int ret = -EINVAL; + + if (layer_id == 0) { + if ((layer_cap & LAYER0_BUSY) + && (layer_cap & LAYER0_AVAIL)) { + ret = 0; + layer_cap &= ~LAYER0_BUSY; + } + } else if (layer_id == 1) { + if ((layer_cap & LAYER1_BUSY) + && (layer_cap & LAYER1_AVAIL)) { + ret = 0; + layer_cap &= ~LAYER1_BUSY; + } + } + return ret; +} + +/********************************************************* + * /dev/amvideo APIs + ******************************************************** + */ +static int amvideo_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +static int amvideo_poll_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +static int amvideo_release(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +static int amvideo_poll_release(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + long ret = 0; + void __user *argp = (void __user *)arg; + struct disp_info_s *layer = &glayer_info[0]; + u32 layer_id; + + switch (cmd) { + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_SET_PIP_ZORDER: + layer = &glayer_info[1]; + break; + default: + break; + } + + if (file->private_data) + layer = (struct disp_info_s *)file->private_data; + + switch (cmd) { + case AMSTREAM_IOC_SET_HDR_INFO:{ +#if ENABLE_UPDATE_HDR_FROM_USER + struct vframe_master_display_colour_s tmp; + + if (copy_from_user(&tmp, argp, sizeof(tmp)) == 0) + config_hdr_info(tmp); +#endif + } + break; + case AMSTREAM_IOC_SET_OMX_VPTS:{ + u32 pts[6]; + + if (copy_from_user(pts, argp, sizeof(pts)) == 0) + set_omx_pts(pts); + } + break; + + case AMSTREAM_IOC_GET_OMX_VPTS: + put_user(omx_pts, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_GET_OMX_VERSION: + put_user(omx_version, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_GET_OMX_INFO: + put_user(omx_info, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_TRICKMODE: + if (arg == TRICKMODE_I) + trickmode_i = 1; + else if (arg == TRICKMODE_FFFB) + trickmode_fffb = 1; + else { + trickmode_i = 0; + trickmode_fffb = 0; + } + to_notify_trick_wait = false; + atomic_set(&trickmode_framedone, 0); + tsync_trick_mode(trickmode_fffb); + break; + + case AMSTREAM_IOC_TRICK_STAT: + put_user(atomic_read(&trickmode_framedone), + (u32 __user *)argp); + break; + + case AMSTREAM_IOC_GET_TRICK_VPTS: + put_user(trickmode_vpts, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_VPAUSE: + tsync_avevent(VIDEO_PAUSE, arg); + break; + + case AMSTREAM_IOC_AVTHRESH: + tsync_set_avthresh(arg); + break; + + case AMSTREAM_IOC_SYNCTHRESH: + tsync_set_syncthresh(arg); + break; + + case AMSTREAM_IOC_SYNCENABLE: + tsync_set_enable(arg); + break; + + case AMSTREAM_IOC_SET_SYNC_ADISCON: + tsync_set_sync_adiscont(arg); + break; + + case AMSTREAM_IOC_SET_SYNC_VDISCON: + tsync_set_sync_vdiscont(arg); + break; + + case AMSTREAM_IOC_GET_SYNC_ADISCON: + put_user(tsync_get_sync_adiscont(), (u32 __user *)argp); + break; + + case AMSTREAM_IOC_GET_SYNC_VDISCON: + put_user(tsync_get_sync_vdiscont(), (u32 __user *)argp); + break; + + case AMSTREAM_IOC_GET_SYNC_ADISCON_DIFF: + put_user(tsync_get_sync_adiscont_diff(), (u32 __user *)argp); + break; + + case AMSTREAM_IOC_GET_SYNC_VDISCON_DIFF: + put_user(tsync_get_sync_vdiscont_diff(), (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_SYNC_ADISCON_DIFF: + tsync_set_sync_adiscont_diff(arg); + break; + + case AMSTREAM_IOC_SET_SYNC_VDISCON_DIFF: + tsync_set_sync_vdiscont_diff(arg); + break; + + case AMSTREAM_IOC_VF_STATUS:{ + struct vframe_states vfsta; + struct vframe_states states; + + video_vf_get_states(&vfsta); + states.vf_pool_size = vfsta.vf_pool_size; + states.buf_avail_num = vfsta.buf_avail_num; + states.buf_free_num = vfsta.buf_free_num; + states.buf_recycle_num = vfsta.buf_recycle_num; + if (copy_to_user(argp, &states, sizeof(states))) + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + put_user(disable_videopip, (u32 __user *)argp); + break; + case AMSTREAM_IOC_GET_VIDEO_DISABLE: + put_user(disable_video, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + { + u32 val; + + if (copy_from_user(&val, argp, sizeof(u32)) == 0) + ret = _videopip_set_disable(val); + else + ret = -EFAULT; + } + break; + case AMSTREAM_IOC_SET_VIDEO_DISABLE: + { + u32 val; + + if (copy_from_user(&val, argp, sizeof(u32)) == 0) + ret = _video_set_disable(val); + else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT: + put_user(enable_video_discontinue_report, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT: + enable_video_discontinue_report = (arg == 0) ? 0 : 1; + break; + + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEO_AXIS: + { + int axis[4]; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + if (video_scaler_mode && (layer->layer_id == 0)) { + axis[0] = content_left; + axis[1] = content_top; + axis[2] = content_w; + axis[3] = content_h; + } else +#endif + { + axis[0] = layer->layer_left; + axis[1] = layer->layer_top; + axis[2] = layer->layer_width; + axis[3] = layer->layer_height; + } + + axis[2] = axis[0] + axis[2] - 1; + axis[3] = axis[1] + axis[3] - 1; + + if (copy_to_user(argp, &axis[0], sizeof(axis)) != 0) + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEO_AXIS: + { + int axis[4]; + + if (copy_from_user(axis, argp, sizeof(axis)) == 0) + _set_video_window(layer, axis); + else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_VIDEO_CROP: + { + int crop[4]; + { + crop[0] = layer->crop_top; + crop[1] = layer->crop_left; + crop[2] = layer->crop_bottom; + crop[3] = layer->crop_right; + } + + if (copy_to_user(argp, &crop[0], sizeof(crop)) != 0) + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEO_CROP: + { + int crop[4]; + + if (copy_from_user(crop, argp, sizeof(crop)) == 0) + _set_video_crop(layer, crop); + else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_SCREEN_MODE: + if (copy_to_user(argp, &layer->wide_mode, sizeof(u32)) != 0) + ret = -EFAULT; + break; + + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_SCREEN_MODE: + { + u32 mode; + + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { + if (mode >= VIDEO_WIDEOPTION_MAX) + ret = -EINVAL; + else if (mode != layer->wide_mode) { + layer->wide_mode = mode; + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif + } + } else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_GET_BLACKOUT_POLICY: + if (copy_to_user(argp, &blackout, sizeof(u32)) != 0) + ret = -EFAULT; + break; + + case AMSTREAM_IOC_SET_BLACKOUT_POLICY:{ + u32 mode; + + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { + if (mode > 2) + ret = -EINVAL; + else + blackout = mode; + } else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY: + if (copy_to_user(argp, &blackout_pip, sizeof(u32)) != 0) + ret = -EFAULT; + break; + + case AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY:{ + u32 mode; + + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { + if (mode > 2) + ret = -EINVAL; + else + blackout_pip = mode; + } else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_CLEAR_VBUF:{ + unsigned long flags; + + while (atomic_read(&video_inirq_flag) > 0 || + atomic_read(&video_unreg_flag) > 0) + schedule(); + spin_lock_irqsave(&lock, flags); + cur_dispbuf = NULL; + spin_unlock_irqrestore(&lock, flags); + } + break; + + case AMSTREAM_IOC_CLEAR_VIDEO: + if (blackout) + safe_disable_videolayer(); + break; + + case AMSTREAM_IOC_CLEAR_PIP_VBUF:{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + cur_pipbuf = NULL; + spin_unlock_irqrestore(&lock, flags); + } + break; + + case AMSTREAM_IOC_CLEAR_VIDEOPIP: + safe_disable_videolayer2(); + break; + + case AMSTREAM_IOC_SET_FREERUN_MODE: + if (arg > FREERUN_DUR) + ret = -EFAULT; + else + freerun_mode = arg; + break; + + case AMSTREAM_IOC_GET_FREERUN_MODE: + put_user(freerun_mode, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_DISABLE_SLOW_SYNC: + if (arg) + disable_slow_sync = 1; + else + disable_slow_sync = 0; + break; + /* + *************************************************************** + *3d process ioctl + **************************************************************** + */ + case AMSTREAM_IOC_SET_3D_TYPE: + { +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + unsigned int set_3d = + VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE; + unsigned int type = (unsigned int)arg; + + if (type != process_3d_type) { + process_3d_type = type; + if (mvc_flag) + process_3d_type |= MODE_3D_MVC; + video_property_changed = 1; + if ((process_3d_type & MODE_3D_FA) + && cur_dispbuf + && !cur_dispbuf->trans_fmt) + /*notify di 3d mode is frame*/ + /*alternative mode,passing two*/ + /*buffer in one frame */ + vf_notify_receiver_by_name( + "deinterlace", + set_3d, + (void *)1); + else + vf_notify_receiver_by_name( + "deinterlace", + set_3d, + (void *)0); + } +#endif + break; + } + case AMSTREAM_IOC_GET_3D_TYPE: +#ifdef TV_3D_FUNCTION_OPEN + put_user(process_3d_type, (u32 __user *)argp); + +#endif + break; + case AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE: +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + { + int source_video_3d_type = VPP_3D_MODE_NULL; + + if (!cur_frame_par) + source_video_3d_type = + VPP_3D_MODE_NULL; + else + get_vpp_3d_mode(process_3d_type, + cur_frame_par->trans_fmt, &source_video_3d_type); + put_user(source_video_3d_type, (u32 __user *)argp); + } +#endif + break; + case AMSTREAM_IOC_SET_VSYNC_UPINT: + vsync_pts_inc_upint = arg; + break; + + case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR: + put_user(vsync_slow_factor, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR: + vsync_slow_factor = arg; + break; + + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: + if (layer->layer_id == 0) { + if (arg != 0) + video_global_output = 1; + else + video_global_output = 0; + } +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) { + if (arg != 0) + pip_global_output = 1; + else + pip_global_output = 0; + } +#endif + break; + + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: + if (layer->layer_id == 0) + put_user(video_global_output, (u32 __user *)argp); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + put_user(pip_global_output, (u32 __user *)argp); +#endif + break; + + case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: { + u32 vsync_duration; + u32 video_onoff_diff = 0; + + vsync_duration = vsync_pts_inc / 90; + video_onoff_diff = + jiffies_to_msecs(jiffies) - video_onoff_time; + + if (video_onoff_state == VIDEO_ENABLE_STATE_IDLE) { + /* wait until 5ms after next vsync */ + msleep(video_onoff_diff < vsync_duration + ? vsync_duration - video_onoff_diff + 5 + : 0); + } + put_user(video_onoff_state, (u32 __user *)argp); + break; + } + + case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED: + put_user(first_frame_toggled, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_VIDEOPEEK: + videopeek = true; + nopostvideostart = true; + break; + + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_GET_ZORDER: + put_user(layer->zorder, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_PIP_ZORDER: + case AMSTREAM_IOC_SET_ZORDER:{ + u32 zorder, new_prop = 0; + + if (copy_from_user(&zorder, argp, sizeof(u32)) == 0) { + if (layer->zorder != zorder) + new_prop = 1; + layer->zorder = zorder; + if ((layer->layer_id == 0) && new_prop) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if ((layer->layer_id == 1) && new_prop) + pip_property_changed = 1; +#endif + } else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_QUERY_LAYER: + mutex_lock(&video_layer_mutex); + put_user(layer_cap, (u32 __user *)argp); + mutex_unlock(&video_layer_mutex); + ret = 0; + break; + + case AMSTREAM_IOC_ALLOC_LAYER: + if (copy_from_user(&layer_id, argp, sizeof(u32)) == 0) { + if (layer_id >= MAX_VD_LAYERS) { + ret = -EINVAL; + } else { + mutex_lock(&video_layer_mutex); + if (file->private_data) { + ret = -EBUSY; + } else { + ret = alloc_layer(layer_id); + if (!ret) + file->private_data = + (void *)&glayer_info[layer_id]; + } + mutex_unlock(&video_layer_mutex); + } + } else + ret = -EFAULT; + break; + + case AMSTREAM_IOC_FREE_LAYER: + mutex_lock(&video_layer_mutex); + if (!file->private_data) { + ret = -EINVAL; + } else { + ret = free_layer(layer->layer_id); + if (!ret) + file->private_data = NULL; + } + mutex_unlock(&video_layer_mutex); + break; + + default: + return -EINVAL; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + long ret = 0; + + switch (cmd) { + case AMSTREAM_IOC_SET_HDR_INFO: + case AMSTREAM_IOC_SET_OMX_VPTS: + case AMSTREAM_IOC_GET_OMX_VPTS: + case AMSTREAM_IOC_GET_OMX_VERSION: + case AMSTREAM_IOC_GET_OMX_INFO: + case AMSTREAM_IOC_TRICK_STAT: + case AMSTREAM_IOC_GET_TRICK_VPTS: + case AMSTREAM_IOC_GET_SYNC_ADISCON: + case AMSTREAM_IOC_GET_SYNC_VDISCON: + case AMSTREAM_IOC_GET_SYNC_ADISCON_DIFF: + case AMSTREAM_IOC_GET_SYNC_VDISCON_DIFF: + case AMSTREAM_IOC_VF_STATUS: + case AMSTREAM_IOC_GET_VIDEO_DISABLE: + case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT: + case AMSTREAM_IOC_GET_VIDEO_AXIS: + case AMSTREAM_IOC_SET_VIDEO_AXIS: + case AMSTREAM_IOC_GET_VIDEO_CROP: + case AMSTREAM_IOC_SET_VIDEO_CROP: + case AMSTREAM_IOC_GET_SCREEN_MODE: + case AMSTREAM_IOC_SET_SCREEN_MODE: + case AMSTREAM_IOC_GET_BLACKOUT_POLICY: + case AMSTREAM_IOC_SET_BLACKOUT_POLICY: + case AMSTREAM_IOC_GET_FREERUN_MODE: + case AMSTREAM_IOC_GET_3D_TYPE: + case AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE: + case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR: + case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: + case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_SET_PIP_ZORDER: + case AMSTREAM_IOC_GET_ZORDER: + case AMSTREAM_IOC_SET_ZORDER: + case AMSTREAM_IOC_QUERY_LAYER: + case AMSTREAM_IOC_ALLOC_LAYER: + case AMSTREAM_IOC_FREE_LAYER: + arg = (unsigned long) compat_ptr(arg); + case AMSTREAM_IOC_TRICKMODE: + case AMSTREAM_IOC_VPAUSE: + case AMSTREAM_IOC_AVTHRESH: + case AMSTREAM_IOC_SYNCTHRESH: + case AMSTREAM_IOC_SYNCENABLE: + case AMSTREAM_IOC_SET_SYNC_ADISCON: + case AMSTREAM_IOC_SET_SYNC_VDISCON: + case AMSTREAM_IOC_SET_SYNC_ADISCON_DIFF: + case AMSTREAM_IOC_SET_SYNC_VDISCON_DIFF: + case AMSTREAM_IOC_SET_VIDEO_DISABLE: + case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT: + case AMSTREAM_IOC_CLEAR_VBUF: + case AMSTREAM_IOC_CLEAR_VIDEO: + case AMSTREAM_IOC_CLEAR_PIP_VBUF: + case AMSTREAM_IOC_CLEAR_VIDEOPIP: + case AMSTREAM_IOC_SET_FREERUN_MODE: + case AMSTREAM_IOC_DISABLE_SLOW_SYNC: + case AMSTREAM_IOC_SET_3D_TYPE: + case AMSTREAM_IOC_SET_VSYNC_UPINT: + case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR: + case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: + case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED: + case AMSTREAM_IOC_SET_VIDEOPEEK: + return amvideo_ioctl(file, cmd, arg); + default: + return -EINVAL; + } + + return ret; +} +#endif + +static unsigned int amvideo_poll(struct file *file, poll_table *wait_table) +{ + poll_wait(file, &amvideo_trick_wait, wait_table); + + if (atomic_read(&trickmode_framedone)) { + atomic_set(&trickmode_framedone, 0); + return POLLOUT | POLLWRNORM; + } + + return 0; +} + +static unsigned int amvideo_poll_poll(struct file *file, poll_table *wait_table) +{ + poll_wait(file, &amvideo_sizechange_wait, wait_table); + + if (atomic_read(&video_sizechange)) { + atomic_set(&video_sizechange, 0); + return POLLIN | POLLWRNORM; + } + + return 0; +} + +static const struct file_operations amvideo_fops = { + .owner = THIS_MODULE, + .open = amvideo_open, + .release = amvideo_release, + .unlocked_ioctl = amvideo_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amvideo_compat_ioctl, +#endif + .poll = amvideo_poll, +}; + +static const struct file_operations amvideo_poll_fops = { + .owner = THIS_MODULE, + .open = amvideo_poll_open, + .release = amvideo_poll_release, + .poll = amvideo_poll_poll, +}; + +/********************************************************* + * SYSFS property functions + *********************************************************/ +#define MAX_NUMBER_PARA 10 +#define AMVIDEO_CLASS_NAME "video" +#define AMVIDEO_POLL_CLASS_NAME "video_poll" + +static int parse_para(const char *para, int para_num, int *result) +{ + char *token = NULL; + char *params, *params_base; + int *out = result; + int len = 0, count = 0; + int res = 0; + int ret = 0; + + if (!para) + return 0; + + params = kstrdup(para, GFP_KERNEL); + params_base = params; + token = params; + if (token) { + len = strlen(token); + do { + token = strsep(¶ms, " "); + if (!token) + break; + while (token && (isspace(*token) + || !isgraph(*token)) && len) { + token++; + len--; + } + if (len == 0) + break; + ret = kstrtoint(token, 0, &res); + if (ret < 0) + break; + len = strlen(token); + *out++ = res; + count++; + } while ((count < para_num) && (len > 0)); + } + + kfree(params_base); + return count; +} + +static void set_video_crop( + struct disp_info_s *layer, const char *para) +{ + int parsed[4]; + + if (likely(parse_para(para, 4, parsed) == 4)) + _set_video_crop(layer, parsed); + amlog_mask(LOG_MASK_SYSFS, + "video crop=>x0:%d,y0:%d,x1:%d,y1:%d\n ", + parsed[0], parsed[1], parsed[2], parsed[3]); +} + +static void set_video_speed_check(const char *para) +{ + int parsed[2]; + struct disp_info_s *layer = &glayer_info[0]; + + if (likely(parse_para(para, 2, parsed) == 2)) { + layer->speed_check_height = parsed[0]; + layer->speed_check_width = parsed[1]; + } + amlog_mask(LOG_MASK_SYSFS, + "video speed_check=>h:%d,w:%d\n ", parsed[0], parsed[1]); +} + +static void set_video_window( + struct disp_info_s *layer, const char *para) +{ + int parsed[4]; + + if (likely(parse_para(para, 4, parsed) == 4)) + _set_video_window(layer, parsed); + amlog_mask(LOG_MASK_SYSFS, + "video=>x0:%d,y0:%d,x1:%d,y1:%d\n ", + parsed[0], parsed[1], parsed[2], parsed[3]); +} + +static ssize_t stereo_scaler_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TV_3D_FUNCTION_OPEN + u32 enable; + int r; + struct disp_info_s *layer = &glayer_info[0]; + + r = kstrtouint(buf, 0, &enable); + if (r < 0) + return -EINVAL; + + layer->vpp_3d_scale = enable ? true : false; + video_property_changed = 1; + amlog_mask(LOG_MASK_SYSFS, "%s:%s 3d scale.\n", __func__, + enable ? "enable" : "disable"); +#endif + return count; +} + +static ssize_t sr_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "super_scaler:%d\n", super_scaler); +} + +static ssize_t sr_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int parsed[1]; + + mutex_lock(&video_module_mutex); + if (likely(parse_para(buf, 1, parsed) == 1)) { + if (super_scaler != (parsed[0] & 0x1)) { + super_scaler = parsed[0] & 0x1; + video_property_changed = 1; + } + } + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t crop_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + u32 t, l, b, r; + struct disp_info_s *layer = &glayer_info[0]; + + t = layer->crop_top; + l = layer->crop_left; + b = layer->crop_bottom; + r = layer->crop_right; + return snprintf(buf, 40, "%d %d %d %d\n", t, l, b, r); +} + +static ssize_t crop_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[0]; + + mutex_lock(&video_module_mutex); + + set_video_crop(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t video_state_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + ssize_t len = 0; + struct vppfilter_mode_s *vpp_filter = NULL; + + if (!cur_frame_par) + return len; + vpp_filter = &cur_frame_par->vpp_filter; + len += sprintf(buf + len, + "zoom_start_x_lines:%u.zoom_end_x_lines:%u.\n", + zoom_start_x_lines, zoom_end_x_lines); + len += sprintf(buf + len, + "zoom_start_y_lines:%u.zoom_end_y_lines:%u.\n", + zoom_start_y_lines, zoom_end_y_lines); + len += sprintf(buf + len, "frame parameters: pic_in_height %u.\n", + cur_frame_par->VPP_pic_in_height_); + len += sprintf(buf + len, + "frame parameters: VPP_line_in_length_ %u.\n", + cur_frame_par->VPP_line_in_length_); + len += sprintf(buf + len, "vscale_skip_count %u.\n", + cur_frame_par->vscale_skip_count); + len += sprintf(buf + len, "hscale_skip_count %u.\n", + cur_frame_par->hscale_skip_count); + len += sprintf(buf + len, "supscl_path %u.\n", + cur_frame_par->supscl_path); + len += sprintf(buf + len, "supsc0_enable %u.\n", + cur_frame_par->supsc0_enable); + len += sprintf(buf + len, "supsc1_enable %u.\n", + cur_frame_par->supsc1_enable); + len += sprintf(buf + len, "supsc0_hori_ratio %u.\n", + cur_frame_par->supsc0_hori_ratio); + len += sprintf(buf + len, "supsc1_hori_ratio %u.\n", + cur_frame_par->supsc1_hori_ratio); + len += sprintf(buf + len, "supsc0_vert_ratio %u.\n", + cur_frame_par->supsc0_vert_ratio); + len += sprintf(buf + len, "supsc1_vert_ratio %u.\n", + cur_frame_par->supsc1_vert_ratio); + len += sprintf(buf + len, "spsc0_h_in %u.\n", + cur_frame_par->spsc0_h_in); + len += sprintf(buf + len, "spsc1_h_in %u.\n", + cur_frame_par->spsc1_h_in); + len += sprintf(buf + len, "spsc0_w_in %u.\n", + cur_frame_par->spsc0_w_in); + len += sprintf(buf + len, "spsc1_w_in %u.\n", + cur_frame_par->spsc1_w_in); + len += sprintf(buf + len, "video_input_w %u.\n", + cur_frame_par->video_input_w); + len += sprintf(buf + len, "video_input_h %u.\n", + cur_frame_par->video_input_h); + len += sprintf(buf + len, "clk_in_pps %u.\n", + cur_frame_par->clk_in_pps); +#ifdef TV_3D_FUNCTION_OPEN + len += sprintf(buf + len, "vpp_2pic_mode %u.\n", + cur_frame_par->vpp_2pic_mode); + len += sprintf(buf + len, "vpp_3d_scale %u.\n", + cur_frame_par->vpp_3d_scale); + len += sprintf(buf + len, + "vpp_3d_mode %u.\n", cur_frame_par->vpp_3d_mode); +#endif + len += + sprintf(buf + len, "hscale phase step 0x%x.\n", + vpp_filter->vpp_hsc_start_phase_step); + len += + sprintf(buf + len, "vscale phase step 0x%x.\n", + vpp_filter->vpp_vsc_start_phase_step); + len += + sprintf(buf + len, "pps pre hsc enable %d.\n", + vpp_filter->vpp_pre_hsc_en); + len += + sprintf(buf + len, "pps pre vsc enable %d.\n", + vpp_filter->vpp_pre_vsc_en); + len += + sprintf(buf + len, "hscale filter coef %d.\n", + vpp_filter->vpp_horz_filter); + len += + sprintf(buf + len, "vscale filter coef %d.\n", + vpp_filter->vpp_vert_filter); + len += + sprintf(buf + len, "vpp_vert_chroma_filter_en %d.\n", + vpp_filter->vpp_vert_chroma_filter_en); + len += + sprintf(buf + len, "post_blend_vd_h_start 0x%x.\n", + cur_frame_par->VPP_post_blend_vd_h_start_); + len += + sprintf(buf + len, "post_blend_vd_h_end 0x%x.\n", + cur_frame_par->VPP_post_blend_vd_h_end_); + len += + sprintf(buf + len, "post_blend_vd_v_start 0x%x.\n", + cur_frame_par->VPP_post_blend_vd_v_start_); + len += + sprintf(buf + len, "post_blend_vd_v_end 0x%x.\n", + cur_frame_par->VPP_post_blend_vd_v_end_); + len += + sprintf(buf + len, "VPP_hd_start_lines_ 0x%x.\n", + cur_frame_par->VPP_hd_start_lines_); + len += + sprintf(buf + len, "VPP_hd_end_lines_ 0x%x.\n", + cur_frame_par->VPP_hd_end_lines_); + len += + sprintf(buf + len, "VPP_vd_start_lines_ 0x%x.\n", + cur_frame_par->VPP_vd_start_lines_); + len += + sprintf(buf + len, "VPP_vd_end_lines_ 0x%x.\n", + cur_frame_par->VPP_vd_end_lines_); + len += + sprintf(buf + len, "VPP_hsc_startp 0x%x.\n", + cur_frame_par->VPP_hsc_startp); + len += + sprintf(buf + len, "VPP_hsc_endp 0x%x.\n", + cur_frame_par->VPP_hsc_endp); + len += + sprintf(buf + len, "VPP_vsc_startp 0x%x.\n", + cur_frame_par->VPP_vsc_startp); + len += + sprintf(buf + len, "VPP_vsc_endp 0x%x.\n", + cur_frame_par->VPP_vsc_endp); + return len; +} + +static ssize_t axis_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + int x, y, w, h; + struct disp_info_s *layer = &glayer_info[0]; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + if (video_scaler_mode) { + x = content_left; + y = content_top; + w = content_w; + h = content_h; + } else +#endif + { + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; + } + return snprintf(buf, 40, "%d %d %d %d\n", x, y, x + w - 1, y + h - 1); +} + +static ssize_t axis_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[0]; + + mutex_lock(&video_module_mutex); + + set_video_window(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t global_offset_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int x, y; + struct disp_info_s *layer = &glayer_info[0]; + + x = layer->global_offset_x; + y = layer->global_offset_y; + + return snprintf(buf, 40, "%d %d\n", x, y); +} + +static ssize_t global_offset_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int parsed[2]; + struct disp_info_s *layer = &glayer_info[0]; + + mutex_lock(&video_module_mutex); + + if (likely(parse_para(buf, 2, parsed) == 2)) { + layer->global_offset_x = parsed[0]; + layer->global_offset_y = parsed[1]; + video_property_changed = 1; + + amlog_mask(LOG_MASK_SYSFS, + "video_offset=>x0:%d,y0:%d\n ", + parsed[0], parsed[1]); + } + + mutex_unlock(&video_module_mutex); + + return count; +} + +static ssize_t zoom_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 r; + struct disp_info_s *layer = &glayer_info[0]; + + r = layer->zoom_ratio; + + return snprintf(buf, 40, "%d\n", r); +} + +static ssize_t zoom_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned long r; + int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; + + ret = kstrtoul(buf, 0, (unsigned long *)&r); + if (ret < 0) + return -EINVAL; + + if ((r <= MAX_ZOOM_RATIO) && (r != layer->zoom_ratio)) { + layer->zoom_ratio = r; + video_property_changed = 1; + } + + return count; +} + +static ssize_t screen_mode_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + struct disp_info_s *layer = &glayer_info[0]; + static const char * const wide_str[] = { + "normal", "full stretch", "4-3", "16-9", "non-linear", + "normal-noscaleup", + "4-3 ignore", "4-3 letter box", "4-3 pan scan", "4-3 combined", + "16-9 ignore", "16-9 letter box", "16-9 pan scan", + "16-9 combined", "Custom AR", "AFD" + }; + + if (layer->wide_mode < ARRAY_SIZE(wide_str)) { + return sprintf(buf, "%d:%s\n", + layer->wide_mode, + wide_str[layer->wide_mode]); + } else + return 0; +} + +static ssize_t screen_mode_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned long mode; + int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; + + ret = kstrtoul(buf, 0, (unsigned long *)&mode); + if (ret < 0) + return -EINVAL; + + if ((mode < VIDEO_WIDEOPTION_MAX) + && (mode != layer->wide_mode)) { + layer->wide_mode = mode; + video_property_changed = 1; + } + + return count; +} + +static ssize_t blackout_policy_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", blackout); +} + +static ssize_t blackout_policy_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &blackout); + if (r < 0) + return -EINVAL; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%d)\n", __func__, blackout); + + return count; +} + +static ssize_t video_seek_flag_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", video_seek_flag); +} + +static ssize_t video_seek_flag_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &video_seek_flag); + if (r < 0) + return -EINVAL; + + return count; +} + +#ifdef PTS_TRACE_DEBUG +static ssize_t pts_trace_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d %d %d %d %d %d\n" + "%d %d %d %d %d %d %d %d\n" + "%0x %0x %0x %0x %0x %0x %0x %0x\n" + "%0x %0x %0x %0x %0x %0x %0x %0x\n" + "%0x %0x %0x %0x %0x %0x %0x %0x\n" + "%0x %0x %0x %0x %0x %0x %0x %0x\n", + pts_trace_his[0], pts_trace_his[1], pts_trace_his[2], + pts_trace_his[3], pts_trace_his[4], pts_trace_his[5], + pts_trace_his[6], pts_trace_his[7], pts_trace_his[8], + pts_trace_his[9], pts_trace_his[10], pts_trace_his[11], + pts_trace_his[12], pts_trace_his[13], pts_trace_his[14], + pts_trace_his[15], + pts_his[0], pts_his[1], pts_his[2], pts_his[3], + pts_his[4], pts_his[5], pts_his[6], pts_his[7], + pts_his[8], pts_his[9], pts_his[10], pts_his[11], + pts_his[12], pts_his[13], pts_his[14], pts_his[15], + scr_his[0], scr_his[1], scr_his[2], scr_his[3], + scr_his[4], scr_his[5], scr_his[6], scr_his[7], + scr_his[8], scr_his[9], scr_his[10], scr_his[11], + scr_his[12], scr_his[13], scr_his[14], scr_his[15]); +} +#endif + +static ssize_t brightness_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + s32 val = (READ_VCBUS_REG(VPP_VADJ1_Y + cur_dev->vpp_off) >> 8) & + 0x1ff; + + val = (val << 23) >> 23; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t brightness_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if ((r < 0) || (val < -255) || (val > 255)) + return -EINVAL; + + if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) + WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y + + cur_dev->vpp_off, val, 8, 9); + else + WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y + + cur_dev->vpp_off, val << 1, 8, 10); + + WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ1_EN); + + return count; +} + +static ssize_t contrast_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", + (int)(READ_VCBUS_REG(VPP_VADJ1_Y + cur_dev->vpp_off) & + 0xff) - 0x80); +} + +static ssize_t contrast_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if ((r < 0) || (val < -127) || (val > 127)) + return -EINVAL; + + val += 0x80; + + WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y + cur_dev->vpp_off, val, 0, 8); + WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ1_EN); + + return count; +} + +static ssize_t vpp_brightness_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + s32 val = (READ_VCBUS_REG(VPP_VADJ2_Y + + cur_dev->vpp_off) >> 8) & 0x1ff; + + val = (val << 23) >> 23; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t vpp_brightness_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if ((r < 0) || (val < -255) || (val > 255)) + return -EINVAL; + + if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) + WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y + + cur_dev->vpp_off, val, 8, 9); + else + WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y + + cur_dev->vpp_off, val << 1, 8, 10); + + WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ2_EN); + + return count; +} + +static ssize_t vpp_contrast_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", + (int)(READ_VCBUS_REG(VPP_VADJ2_Y + cur_dev->vpp_off) & + 0xff) - 0x80); +} + +static ssize_t vpp_contrast_store(struct class *cla, + struct class_attribute *attr, const char *buf, + size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if ((r < 0) || (val < -127) || (val > 127)) + return -EINVAL; + + val += 0x80; + + WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y + cur_dev->vpp_off, val, 0, 8); + WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ2_EN); + + return count; +} + +static ssize_t saturation_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", + READ_VCBUS_REG(VPP_VADJ1_Y + cur_dev->vpp_off) & 0xff); +} + +static ssize_t saturation_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if ((r < 0) || (val < -127) || (val > 127)) + return -EINVAL; + + WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y + cur_dev->vpp_off, val, 0, 8); + WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ1_EN); + + return count; +} + +static ssize_t vpp_saturation_hue_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%x\n", READ_VCBUS_REG(VPP_VADJ2_MA_MB)); +} + +static ssize_t vpp_saturation_hue_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + s32 mab = 0; + s16 mc = 0, md = 0; + + r = kstrtoint(buf, 0, &mab); + if ((r < 0) || (mab & 0xfc00fc00)) + return -EINVAL; + + WRITE_VCBUS_REG(VPP_VADJ2_MA_MB, mab); + mc = (s16) ((mab << 22) >> 22); /* mc = -mb */ + mc = 0 - mc; + if (mc > 511) + mc = 511; + if (mc < -512) + mc = -512; + md = (s16) ((mab << 6) >> 22); /* md = ma; */ + mab = ((mc & 0x3ff) << 16) | (md & 0x3ff); + WRITE_VCBUS_REG(VPP_VADJ2_MC_MD, mab); + /* WRITE_MPEG_REG(VPP_VADJ_CTRL, 1); */ + WRITE_VCBUS_REG_BITS(VPP_VADJ_CTRL + cur_dev->vpp_off, 1, 2, 1); +#ifdef PQ_DEBUG_EN + pr_info("\n[amvideo..] set vpp_saturation OK!!!\n"); +#endif + return count; +} + +/* [ 24] 1/enable, 0/disable */ +/* [23:16] Y */ +/* [15: 8] Cb */ +/* [ 7: 0] Cr */ +static ssize_t test_screen_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%x\n", test_screen); +} +static ssize_t rgb_screen_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%x\n", rgb_screen); +} + +#define SCALE 6 + +static short R_Cr[] = { -11484, -11394, -11305, -11215, -11125, +-11036, -10946, -10856, -10766, -10677, -10587, -10497, -10407, +-10318, -10228, -10138, -10049, -9959, -9869, -9779, -9690, -9600, +-9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882, -8792, -8703, +-8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985, -7895, -7805, +-7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088, -6998, -6908, +-6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190, -6101, -6011, +-5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293, -5203, -5113, +-5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396, -4306, -4216, +-4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498, -3409, -3319, +-3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601, -2511, -2422, +-2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704, -1614, -1524, +-1435, -1345, -1255, -1165, -1076, -986, -896, -807, -717, -627, -537, +-448, -358, -268, -178, -89, 0, 90, 179, 269, 359, 449, 538, 628, 718, +808, 897, 987, 1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795, +1884, 1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782, +2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679, 3769, +3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576, 4666, 4756, +4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473, 5563, 5653, 5743, +5832, 5922, 6012, 6102, 6191, 6281, 6371, 6460, 6550, 6640, 6730, +6819, 6909, 6999, 7089, 7178, 7268, 7358, 7447, 7537, 7627, 7717, +7806, 7896, 7986, 8076, 8165, 8255, 8345, 8434, 8524, 8614, 8704, +8793, 8883, 8973, 9063, 9152, 9242, 9332, 9421, 9511, 9601, 9691, +9780, 9870, 9960, 10050, 10139, 10229, 10319, 10408, 10498, 10588, +10678, 10767, 10857, 10947, 11037, 11126, 11216, 11306, 11395 }; + +static short G_Cb[] = { 2819, 2797, 2775, 2753, 2731, 2709, 2687, +2665, 2643, 2621, 2599, 2577, 2555, 2533, 2511, 2489, 2467, 2445, +2423, 2401, 2379, 2357, 2335, 2313, 2291, 2269, 2247, 2225, 2202, +2180, 2158, 2136, 2114, 2092, 2070, 2048, 2026, 2004, 1982, 1960, +1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784, 1762, 1740, 1718, +1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520, 1498, 1476, +1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255, 1233, +1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991, 969, +947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727, 705, 683, 661, +639, 617, 595, 573, 551, 529, 507, 485, 463, 440, 418, 396, 374, 352, +330, 308, 286, 264, 242, 220, 198, 176, 154, 132, 110, 88, 66, 44, 22, +0, -21, -43, -65, -87, -109, -131, -153, -175, -197, -219, -241, -263, +-285, -307, -329, -351, -373, -395, -417, -439, -462, -484, -506, +-528, -550, -572, -594, -616, -638, -660, -682, -704, -726, -748, +-770, -792, -814, -836, -858, -880, -902, -924, -946, -968, -990, +-1012, -1034, -1056, -1078, -1100, -1122, -1144, -1166, -1188, -1210, +-1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387, -1409, -1431, +-1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651, +-1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871, +-1893, -1915, -1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091, +-2113, -2135, -2157, -2179, -2201, -2224, -2246, -2268, -2290, -2312, +-2334, -2356, -2378, -2400, -2422, -2444, -2466, -2488, -2510, -2532, +-2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708, -2730, -2752, +-2774, -2796 }; + +static short G_Cr[] = { 5850, 5805, 5759, 5713, 5667, 5622, 5576, +5530, 5485, 5439, 5393, 5347, 5302, 5256, 5210, 5165, 5119, 5073, +5028, 4982, 4936, 4890, 4845, 4799, 4753, 4708, 4662, 4616, 4570, +4525, 4479, 4433, 4388, 4342, 4296, 4251, 4205, 4159, 4113, 4068, +4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702, 3656, 3611, 3565, +3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154, 3108, 3062, +3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605, 2559, +2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057, +2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554, +1508, 1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051, +1006, 960, 914, 868, 823, 777, 731, 686, 640, 594, 548, 503, 457, 411, +366, 320, 274, 229, 183, 137, 91, 46, 0, -45, -90, -136, -182, -228, +-273, -319, -365, -410, -456, -502, -547, -593, -639, -685, -730, +-776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187, +-1233, -1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644, +-1690, -1736, -1781, -1827, -1873, -1919, -1964, -2010, -2056, -2101, +-2147, -2193, -2239, -2284, -2330, -2376, -2421, -2467, -2513, -2558, +-2604, -2650, -2696, -2741, -2787, -2833, -2878, -2924, -2970, -3016, +-3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427, -3473, +-3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930, +-3975, -4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387, +-4432, -4478, -4524, -4569, -4615, -4661, -4707, -4752, -4798, -4844, +-4889, -4935, -4981, -5027, -5072, -5118, -5164, -5209, -5255, -5301, +-5346, -5392, -5438, -5484, -5529, -5575, -5621, -5666, -5712, -5758, +-5804 }; + +static short B_Cb[] = { -14515, -14402, -14288, -14175, -14062, +-13948, -13835, -13721, -13608, -13495, -13381, -13268, -13154, +-13041, -12928, -12814, -12701, -12587, -12474, -12360, -12247, +-12134, -12020, -11907, -11793, -11680, -11567, -11453, -11340, +-11226, -11113, -11000, -10886, -10773, -10659, -10546, -10433, +-10319, -10206, -10092, -9979, -9865, -9752, -9639, -9525, -9412, +-9298, -9185, -9072, -8958, -8845, -8731, -8618, -8505, -8391, -8278, +-8164, -8051, -7938, -7824, -7711, -7597, -7484, -7371, -7257, -7144, +-7030, -6917, -6803, -6690, -6577, -6463, -6350, -6236, -6123, -6010, +-5896, -5783, -5669, -5556, -5443, -5329, -5216, -5102, -4989, -4876, +-4762, -4649, -4535, -4422, -4309, -4195, -4082, -3968, -3855, -3741, +-3628, -3515, -3401, -3288, -3174, -3061, -2948, -2834, -2721, -2607, +-2494, -2381, -2267, -2154, -2040, -1927, -1814, -1700, -1587, -1473, +-1360, -1246, -1133, -1020, -906, -793, -679, -566, -453, -339, -226, +-112, 0, 113, 227, 340, 454, 567, 680, 794, 907, 1021, 1134, 1247, +1361, 1474, 1588, 1701, 1815, 1928, 2041, 2155, 2268, 2382, 2495, +2608, 2722, 2835, 2949, 3062, 3175, 3289, 3402, 3516, 3629, 3742, +3856, 3969, 4083, 4196, 4310, 4423, 4536, 4650, 4763, 4877, 4990, +5103, 5217, 5330, 5444, 5557, 5670, 5784, 5897, 6011, 6124, 6237, +6351, 6464, 6578, 6691, 6804, 6918, 7031, 7145, 7258, 7372, 7485, +7598, 7712, 7825, 7939, 8052, 8165, 8279, 8392, 8506, 8619, 8732, +8846, 8959, 9073, 9186, 9299, 9413, 9526, 9640, 9753, 9866, 9980, +10093, 10207, 10320, 10434, 10547, 10660, 10774, 10887, 11001, 11114, +11227, 11341, 11454, 11568, 11681, 11794, 11908, 12021, 12135, 12248, +12361, 12475, 12588, 12702, 12815, 12929, 13042, 13155, 13269, 13382, +13496, 13609, 13722, 13836, 13949, 14063, 14176, 14289, 14403 +}; + +static u32 yuv2rgb(u32 yuv) +{ + int y = (yuv >> 16) & 0xff; + int cb = (yuv >> 8) & 0xff; + int cr = yuv & 0xff; + int r, g, b; + + r = y + ((R_Cr[cr]) >> SCALE); + g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE); + b = y + ((B_Cb[cb]) >> SCALE); + + r = r - 16; + if (r < 0) + r = 0; + r = r*1164/1000; + g = g - 16; + if (g < 0) + g = 0; + g = g*1164/1000; + b = b - 16; + if (b < 0) + b = 0; + b = b*1164/1000; + + r = (r <= 0) ? 0 : (r >= 255) ? 255 : r; + g = (g <= 0) ? 0 : (g >= 255) ? 255 : g; + b = (b <= 0) ? 0 : (b >= 255) ? 255 : b; + + return (r << 16) | (g << 8) | b; +} +/* 8bit convert to 10bit */ +static u32 eight2ten(u32 yuv) +{ + int y = (yuv >> 16) & 0xff; + int cb = (yuv >> 8) & 0xff; + int cr = yuv & 0xff; + u32 data32; + + /* txlx need check vd1 path bit width by s2u registers */ + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX) { + data32 = READ_VCBUS_REG(0x1d94) & 0xffff; + if ((data32 == 0x2000) || + (data32 == 0x800)) + return ((y << 20)<<2) | ((cb << 10)<<2) | (cr<<2); + else + return (y << 20) | (cb << 10) | cr; + } else + return (y << 20) | (cb << 10) | cr; +} + +static u32 rgb2yuv(u32 rgb) +{ + int r = (rgb >> 16) & 0xff; + int g = (rgb >> 8) & 0xff; + int b = rgb & 0xff; + int y, u, v; + + y = ((47*r + 157*g + 16*b + 128) >> 8) + 16; + u = ((-26*r - 87*g + 112*b + 128) >> 8) + 128; + v = ((112*r - 102*g - 10*b + 128) >> 8) + 128; + + return (y << 16) | (u << 8) | v; +} + +static ssize_t test_screen_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + unsigned int data = 0x0; + + r = kstrtoint(buf, 0, &test_screen); + if (r < 0) + return -EINVAL; + +#if DEBUG_TMP + if (test_screen & 0x04000000) + data |= VPP_VD2_PREBLEND; + else + data &= (~VPP_VD2_PREBLEND); + + if (test_screen & 0x08000000) + data |= VPP_VD2_POSTBLEND; + else + data &= (~VPP_VD2_POSTBLEND); +#endif + + /* show test screen YUV blend*/ + if (!legacy_vpp) + WRITE_VCBUS_REG( + VPP_POST_BLEND_BLEND_DUMMY_DATA, + test_screen & 0x00ffffff); + else if (is_meson_gxm_cpu() || + (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX)) + /* bit width change to 10bit in gxm, 10/12 in txlx*/ + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + eight2ten(test_screen & 0x00ffffff)); + else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + yuv2rgb(test_screen & 0x00ffffff)); + else if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB) + if (READ_VCBUS_REG(VIU_OSD1_BLK0_CFG_W0) & 0x80) + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + test_screen & 0x00ffffff); + else /* RGB blend */ + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + yuv2rgb(test_screen & 0x00ffffff)); + else + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + test_screen & 0x00ffffff); + if (debug_flag & DEBUG_FLAG_BLACKOUT) { + pr_info("%s write(VPP_MISC,%x) write(VPP_DUMMY_DATA1, %x)\n", + __func__, data, test_screen & 0x00ffffff); + } + return count; +} + +static ssize_t rgb_screen_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + u32 yuv_eight; + + /* unsigned data = 0x0; */ + r = kstrtoint(buf, 0, &rgb_screen); + if (r < 0) + return -EINVAL; + +#if DEBUG_TMP + /* vdin0 pre post blend enable or disabled */ + + data = READ_VCBUS_REG(VPP_MISC); + if (rgb_screen & 0x01000000) + data |= VPP_VD1_PREBLEND; + else + data &= (~VPP_VD1_PREBLEND); + + if (rgb_screen & 0x02000000) + data |= VPP_VD1_POSTBLEND; + else + data &= (~VPP_VD1_POSTBLEND); + + if (test_screen & 0x04000000) + data |= VPP_VD2_PREBLEND; + else + data &= (~VPP_VD2_PREBLEND); + + if (test_screen & 0x08000000) + data |= VPP_VD2_POSTBLEND; + else + data &= (~VPP_VD2_POSTBLEND); +#endif + /* show test screen YUV blend*/ + yuv_eight = rgb2yuv(rgb_screen & 0x00ffffff); + if (!legacy_vpp) { + WRITE_VCBUS_REG( + VPP_POST_BLEND_BLEND_DUMMY_DATA, + yuv_eight & 0x00ffffff); + } else if (is_meson_gxtvbb_cpu()) { + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + rgb_screen & 0x00ffffff); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + WRITE_VCBUS_REG(VPP_DUMMY_DATA1, + eight2ten(yuv_eight & 0x00ffffff)); + } + /* WRITE_VCBUS_REG(VPP_MISC, data); */ + + if (debug_flag & DEBUG_FLAG_BLACKOUT) { + pr_info("%s write(VPP_DUMMY_DATA1, %x)\n", + __func__, rgb_screen & 0x00ffffff); + } + return count; +} + + + +static ssize_t nonlinear_factor_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 factor; + struct disp_info_s *layer = &glayer_info[0]; + + factor = vpp_get_nonlinear_factor(layer); + + return sprintf(buf, "%d\n", factor); +} + +static ssize_t nonlinear_factor_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + u32 factor; + struct disp_info_s *layer = &glayer_info[0]; + + r = kstrtoint(buf, 0, &factor); + if (r < 0) + return -EINVAL; + + if (vpp_set_nonlinear_factor(layer, factor) == 0) + video_property_changed = 1; + + return count; +} + +static ssize_t disable_video_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", disable_video); +} + +static ssize_t disable_video_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%s)\n", __func__, buf); + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + if (_video_set_disable(val) < 0) + return -EINVAL; + + return count; +} + +static ssize_t video_global_output_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", video_global_output); +} + +static ssize_t video_global_output_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &video_global_output); + if (r < 0) + return -EINVAL; + + pr_info("%s(%d)\n", __func__, video_global_output); + + return count; +} + +static ssize_t hold_video_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", hold_video); +} + +static ssize_t hold_video_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + cur_width = 0; + cur_height = 0; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%s)\n", __func__, buf); + + r = kstrtoint(buf, 0, &hold_video); + if (r < 0) + return -EINVAL; + + return count; +} + +static ssize_t freerun_mode_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", freerun_mode); +} + +static ssize_t freerun_mode_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &freerun_mode); + if (r < 0) + return -EINVAL; + + if (debug_flag) + pr_info("%s(%d)\n", __func__, freerun_mode); + + return count; +} + +static ssize_t video_speed_check_h_w_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + u32 h, w; + struct disp_info_s *layer = &glayer_info[0]; + + h = layer->speed_check_height; + w = layer->speed_check_width; + + return snprintf(buf, 40, "%d %d\n", h, w); +} + +static ssize_t video_speed_check_h_w_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + set_video_speed_check(buf); + return strnlen(buf, count); +} + +static ssize_t threedim_mode_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t len) +{ +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + u32 type; + int r; + + r = kstrtoint(buf, 0, &type); + if (r < 0) + return -EINVAL; + + if (type != process_3d_type) { + process_3d_type = type; + if (mvc_flag) + process_3d_type |= MODE_3D_MVC; + video_property_changed = 1; + if ((process_3d_type & MODE_3D_FA) + && cur_dispbuf && !cur_dispbuf->trans_fmt) + /*notify di 3d mode is frame alternative mode,1*/ + /*passing two buffer in one frame */ + vf_notify_receiver_by_name("deinterlace", + VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE, + (void *)1); + else + vf_notify_receiver_by_name("deinterlace", + VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE, + (void *)0); + } +#endif + return len; +} + +static ssize_t threedim_mode_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ +#ifdef TV_3D_FUNCTION_OPEN + return sprintf(buf, "process type 0x%x,trans fmt %u.\n", + process_3d_type, video_3d_format); +#else + return 0; +#endif +} + +static ssize_t frame_addr_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + struct canvas_s canvas; + u32 addr[3]; + + if (cur_dispbuf) { + canvas_read(cur_dispbuf->canvas0Addr & 0xff, &canvas); + addr[0] = canvas.addr; + canvas_read((cur_dispbuf->canvas0Addr >> 8) & 0xff, &canvas); + addr[1] = canvas.addr; + canvas_read((cur_dispbuf->canvas0Addr >> 16) & 0xff, &canvas); + addr[2] = canvas.addr; + + return sprintf(buf, "0x%x-0x%x-0x%x\n", addr[0], addr[1], + addr[2]); + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_canvas_width_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + struct canvas_s canvas; + u32 width[3]; + + if (cur_dispbuf) { + canvas_read(cur_dispbuf->canvas0Addr & 0xff, &canvas); + width[0] = canvas.width; + canvas_read((cur_dispbuf->canvas0Addr >> 8) & 0xff, &canvas); + width[1] = canvas.width; + canvas_read((cur_dispbuf->canvas0Addr >> 16) & 0xff, &canvas); + width[2] = canvas.width; + + return sprintf(buf, "%d-%d-%d\n", + width[0], width[1], width[2]); + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_canvas_height_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + struct canvas_s canvas; + u32 height[3]; + + if (cur_dispbuf) { + canvas_read(cur_dispbuf->canvas0Addr & 0xff, &canvas); + height[0] = canvas.height; + canvas_read((cur_dispbuf->canvas0Addr >> 8) & 0xff, &canvas); + height[1] = canvas.height; + canvas_read((cur_dispbuf->canvas0Addr >> 16) & 0xff, &canvas); + height[2] = canvas.height; + + return sprintf(buf, "%d-%d-%d\n", height[0], height[1], + height[2]); + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_width_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + if (hold_video == 1) + return sprintf(buf, "%d\n", cur_width); + if (cur_dispbuf) { + if (cur_dispbuf->type & VIDTYPE_COMPRESS) + return sprintf(buf, "%d\n", cur_dispbuf->compWidth); + else + return sprintf(buf, "%d\n", cur_dispbuf->width); + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_height_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + if (hold_video == 1) + return sprintf(buf, "%d\n", cur_height); + if (cur_dispbuf) { + if (cur_dispbuf->type & VIDTYPE_COMPRESS) + return sprintf(buf, "%d\n", cur_dispbuf->compHeight); + else + return sprintf(buf, "%d\n", cur_dispbuf->height); + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_format_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + if (cur_dispbuf) { + if ((cur_dispbuf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) + ret = sprintf(buf, "interlace-top\n"); + else if ((cur_dispbuf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_BOTTOM) + ret = sprintf(buf, "interlace-bottom\n"); + else + ret = sprintf(buf, "progressive\n"); + + if (cur_dispbuf->type & VIDTYPE_COMPRESS) + ret += sprintf(buf + ret, "Compressed\n"); + + return ret; + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_aspect_ratio_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + if (cur_dispbuf) { + u32 ar = (cur_dispbuf->ratio_control & + DISP_RATIO_ASPECT_RATIO_MASK) >> + DISP_RATIO_ASPECT_RATIO_BIT; + + if (ar) + return sprintf(buf, "0x%x\n", ar); + else + return sprintf(buf, "0x%x\n", + (cur_dispbuf->width << 8) / + cur_dispbuf->height); + } + + return sprintf(buf, "NA\n"); +} + +static ssize_t frame_rate_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + u32 cnt = frame_count - last_frame_count; + u32 time = jiffies; + u32 tmp = time; + u32 rate = 0; + u32 vsync_rate; + ssize_t ret = 0; + + time -= last_frame_time; + last_frame_time = tmp; + last_frame_count = frame_count; + if (time == 0) + return 0; + rate = 100 * cnt * HZ / time; + vsync_rate = 100 * vsync_count * HZ / time; + if (vinfo->sync_duration_den > 0) { + ret = + sprintf(buf, + "VF.fps=%d.%02d panel fps %d, dur/is: %d,v/s=%d.%02d,inc=%d\n", + rate / 100, rate % 100, + vinfo->sync_duration_num / + vinfo->sync_duration_den, + time, vsync_rate / 100, vsync_rate % 100, + vsync_pts_inc); + } + if ((debugflags & DEBUG_FLAG_CALC_PTS_INC) && time > HZ * 10 + && vsync_rate > 0) { + if ((vsync_rate * vsync_pts_inc / 100) != 90000) + vsync_pts_inc = 90000 * 100 / (vsync_rate); + } + vsync_count = 0; + return ret; +} + +static ssize_t vframe_states_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + struct vframe_states states; + unsigned long flags; + struct vframe_s *vf; + + if (video_vf_get_states(&states) == 0) { + ret += sprintf(buf + ret, "vframe_pool_size=%d\n", + states.vf_pool_size); + ret += sprintf(buf + ret, "vframe buf_free_num=%d\n", + states.buf_free_num); + ret += sprintf(buf + ret, "vframe buf_recycle_num=%d\n", + states.buf_recycle_num); + ret += sprintf(buf + ret, "vframe buf_avail_num=%d\n", + states.buf_avail_num); + + spin_lock_irqsave(&lock, flags); + + vf = video_vf_peek(); + if (vf) { + ret += sprintf(buf + ret, + "vframe ready frame delayed =%dms\n", + (int)(jiffies_64 - + vf->ready_jiffies64) * 1000 / + HZ); + ret += sprintf(buf + ret, + "vf index=%d\n", vf->index); + ret += sprintf(buf + ret, + "vf->pts=%d\n", vf->pts); + ret += sprintf(buf + ret, + "cur vpts=%d\n", + timestamp_vpts_get()); + ret += sprintf(buf + ret, + "vf type=%d\n", + vf->type); + if (vf->type & VIDTYPE_COMPRESS) { + ret += sprintf(buf + ret, + "vf compHeadAddr=%x\n", + vf->compHeadAddr); + ret += sprintf(buf + ret, + "vf compBodyAddr =%x\n", + vf->compBodyAddr); + } else { + ret += sprintf(buf + ret, + "vf canvas0Addr=%x\n", + vf->canvas0Addr); + ret += sprintf(buf + ret, + "vf canvas1Addr=%x\n", + vf->canvas1Addr); + ret += sprintf(buf + ret, + "vf canvas0Addr.y.addr=%x(%d)\n", + canvas_get_addr( + canvasY(vf->canvas0Addr)), + canvas_get_addr( + canvasY(vf->canvas0Addr))); + ret += sprintf(buf + ret, + "vf canvas0Adr.uv.adr=%x(%d)\n", + canvas_get_addr( + canvasUV(vf->canvas0Addr)), + canvas_get_addr( + canvasUV(vf->canvas0Addr))); + } + } + spin_unlock_irqrestore(&lock, flags); + + } else + ret += sprintf(buf + ret, "vframe no states\n"); + + return ret; +} + +#ifdef CONFIG_AM_VOUT +static ssize_t device_resolution_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + const struct vinfo_s *info; + + if (cur_dev == &video_dev[0]) + info = get_current_vinfo(); + else + info = get_current_vinfo2(); +#else + const struct vinfo_s *info = get_current_vinfo(); +#endif + + if (info != NULL) + return sprintf(buf, "%dx%d\n", info->width, info->height); + else + return sprintf(buf, "0x0\n"); +} +#endif + +static ssize_t file_name_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", file_name); +} + +static ssize_t file_name_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + size_t r; + + /* check input buf to mitigate buffer overflow issue */ + if (strlen(buf) >= sizeof(file_name)) { + memcpy(file_name, buf, sizeof(file_name)); + file_name[sizeof(file_name)-1] = '\0'; + r = 1; + } else + r = sscanf(buf, "%s", file_name); + if (r != 1) + return -EINVAL; + + return r; +} + +static ssize_t debugflags_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len += sprintf(buf + len, "value=%d\n", debugflags); + len += sprintf(buf + len, "bit0:playing as fast!\n"); + len += sprintf(buf + len, + "bit1:enable calc pts inc in frame rate show\n"); + return len; +} + +static ssize_t debugflags_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int value = -1; + +/* + * r = sscanf(buf, "%d", &value); + * if (r == 1) { + * debugflags = value; + * seted = 1; + * } else { + * r = sscanf(buf, "0x%x", &value); + * if (r == 1) { + * debugflags = value; + * seted = 1; + * } + * } + */ + + r = kstrtoint(buf, 0, &value); + if (r < 0) + return -EINVAL; + + debugflags = value; + + pr_info("debugflags changed to %d(%x)\n", debugflags, + debugflags); + return count; + +} + +static ssize_t trickmode_duration_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "trickmode frame duration %d\n", + trickmode_duration / 9000); +} + +static ssize_t trickmode_duration_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + u32 s_value; + + r = kstrtoint(buf, 0, &s_value); + if (r < 0) + return -EINVAL; + + trickmode_duration = s_value * 9000; + + return count; +} + +static ssize_t vsync_pts_inc_upint_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + if (vsync_pts_inc_upint) + return sprintf(buf, + "%d,freerun %d,1.25xInc %d,1.12xInc %d,inc+10 %d,1xInc %d\n", + vsync_pts_inc_upint, vsync_freerun, + vsync_pts_125, vsync_pts_112, vsync_pts_101, + vsync_pts_100); + else + return sprintf(buf, "%d\n", vsync_pts_inc_upint); +} + +static ssize_t vsync_pts_inc_upint_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &vsync_pts_inc_upint); + if (r < 0) + return -EINVAL; + + if (debug_flag) + pr_info("%s(%d)\n", __func__, vsync_pts_inc_upint); + + return count; +} + +static ssize_t slowsync_repeat_enable_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "slowsync repeate enable = %d\n", + slowsync_repeat_enable); +} + +static ssize_t slowsync_repeat_enable_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &slowsync_repeat_enable); + if (r < 0) + return -EINVAL; + + if (debug_flag) + pr_info("%s(%d)\n", __func__, slowsync_repeat_enable); + + return count; +} + +static ssize_t vsync_slow_factor_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", vsync_slow_factor); +} + +static ssize_t vsync_slow_factor_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &vsync_slow_factor); + if (r < 0) + return -EINVAL; + + if (debug_flag) + pr_info("%s(%d)\n", __func__, vsync_slow_factor); + + return count; +} + +static ssize_t vframe_ready_cnt_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int ret = -1; + struct vframe_states states; + + ret = video_vf_get_states(&states); + + return snprintf(buf, 10, "%d\n", (ret == 0) ? + states.buf_avail_num : 0); +} + +static ssize_t fps_info_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + u32 cnt = frame_count - last_frame_count; + u32 time = jiffies; + u32 input_fps = 0; + u32 tmp = time; + + time -= last_frame_time; + last_frame_time = tmp; + last_frame_count = frame_count; + if (time != 0) + output_fps = cnt * HZ / time; + if (cur_dispbuf && cur_dispbuf->duration > 0) { + input_fps = 96000 / cur_dispbuf->duration; + if (output_fps > input_fps) + output_fps = input_fps; + } else + input_fps = output_fps; + return sprintf(buf, "input_fps:0x%x output_fps:0x%x drop_fps:0x%x\n", + input_fps, output_fps, input_fps - output_fps); +} + +static ssize_t video_layer1_state_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + /*return sprintf(buf, "%d\n",*/ + /*(READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off)*/ + /*& VPP_VD1_PREBLEND) ? 1 : 0);*/ + return sprintf(buf, "%d\n", video_enabled); +} + +void set_video_angle(u32 s_value) +{ + struct disp_info_s *layer = &glayer_info[0]; + + if ((s_value <= 3) && (layer->angle != s_value)) { + layer->angle = s_value; + pr_info("video angle:%d\n", layer->angle); + } +} +EXPORT_SYMBOL(set_video_angle); + +static ssize_t angle_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[0]; + + return snprintf(buf, 40, "%d\n", layer->angle); +} + +static ssize_t angle_store(struct class *cla, + struct class_attribute *attr, const char *buf, + size_t count) +{ + int r; + u32 s_value; + + r = kstrtoint(buf, 0, &s_value); + if (r < 0) + return -EINVAL; + + set_video_angle(s_value); + return strnlen(buf, count); +} + +static ssize_t show_first_frame_nosync_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", show_first_frame_nosync ? 1 : 0); +} + +static ssize_t show_first_frame_nosync_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int value; + + r = kstrtoint(buf, 0, &value); + if (r < 0) + return -EINVAL; + + if (value == 0) + show_first_frame_nosync = false; + else + show_first_frame_nosync = true; + + return count; +} + +static ssize_t show_first_picture_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int value; + + r = kstrtoint(buf, 0, &value); + if (r < 0) + return -EINVAL; + + if (value == 0) + show_first_picture = false; + else + show_first_picture = true; + + return count; +} + +static ssize_t free_keep_buffer_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%s)\n", __func__, buf); + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + if (val == 1) + try_free_keep_video(1); + return count; +} + + +static ssize_t free_cma_buffer_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + if (val == 1) { + pr_info("start to free cma buffer\n"); +#if DEBUG_TMP + vh265_free_cmabuf(); + vh264_4k_free_cmabuf(); + vdec_free_cmabuf(); +#endif + } + return count; +} + +static ssize_t pic_mode_info_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + if (cur_dispbuf) { + u32 adapted_mode = (cur_dispbuf->ratio_control + & DISP_RATIO_ADAPTED_PICMODE) ? 1 : 0; + u32 info_frame = (cur_dispbuf->ratio_control + & DISP_RATIO_INFOFRAME_AVAIL) ? 1 : 0; + + ret += sprintf(buf + ret, "ratio_control=0x%x\n", + cur_dispbuf->ratio_control); + ret += sprintf(buf + ret, "adapted_mode=%d\n", + adapted_mode); + ret += sprintf(buf + ret, "info_frame=%d\n", + info_frame); + ret += sprintf(buf + ret, + "hs=%d, he=%d, vs=%d, ve=%d\n", + cur_dispbuf->pic_mode.hs, + cur_dispbuf->pic_mode.he, + cur_dispbuf->pic_mode.vs, + cur_dispbuf->pic_mode.ve); + ret += sprintf(buf + ret, "screen_mode=%d\n", + cur_dispbuf->pic_mode.screen_mode); + ret += sprintf(buf + ret, "custom_ar=%d\n", + cur_dispbuf->pic_mode.custom_ar); + ret += sprintf(buf + ret, "AFD_enable=%d\n", + cur_dispbuf->pic_mode.AFD_enable); + return ret; + } + return sprintf(buf, "NA\n"); +} + +static ssize_t video_inuse_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + size_t r; + + mutex_lock(&video_inuse_mutex); + if (video_inuse == 0) { + r = sprintf(buf, "%d\n", video_inuse); + video_inuse = 1; + pr_info("video_inuse return 0,set 1\n"); + } else { + r = sprintf(buf, "%d\n", video_inuse); + pr_info("video_inuse = %d\n", video_inuse); + } + mutex_unlock(&video_inuse_mutex); + return r; +} + +static ssize_t video_inuse_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + size_t r; + int val; + + mutex_lock(&video_inuse_mutex); + r = kstrtoint(buf, 0, &val); + pr_info("set video_inuse val:%d\n", val); + video_inuse = val; + mutex_unlock(&video_inuse_mutex); + if (r != 1) + return -EINVAL; + + return count; +} + +static ssize_t video_zorder_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[0]; + + return sprintf(buf, "%d\n", layer->zorder); +} + +static ssize_t video_zorder_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int zorder; + int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; + + ret = kstrtoint(buf, 0, &zorder); + if (ret < 0) + return -EINVAL; + + if (zorder != layer->zorder) { + layer->zorder = zorder; + video_property_changed = 1; + } + return count; +} + +static ssize_t black_threshold_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "width: %d, height: %d\n", + black_threshold_width, + black_threshold_height); +} + +static ssize_t black_threshold_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int parsed[2]; + + if (likely(parse_para(buf, 2, parsed) == 2)) { + black_threshold_width = parsed[0]; + black_threshold_height = parsed[1]; + } + return strnlen(buf, count); +} + +static int free_alloced_hist_test_buffer(void) +{ + if (hist_buffer_addr) { + codec_mm_free_for_dma("hist-test", hist_buffer_addr); + hist_buffer_addr = 0; + } + return 0; +} + +static int alloc_hist_test_buffer(u32 size) +{ + int ret = -ENOMEM; + int flags = CODEC_MM_FLAGS_DMA | + CODEC_MM_FLAGS_FOR_VDECODER; + + if (!hist_buffer_addr) { + hist_buffer_addr = codec_mm_alloc_for_dma( + "hist-test", + PAGE_ALIGN(size)/PAGE_SIZE, 0, flags); + } + if (hist_buffer_addr) + ret = 0; + return ret; +} + +static ssize_t hist_test_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ +#define VI_HIST_MAX_MIN (0x2e03) +#define VI_HIST_SPL_VAL (0x2e04) +#define VI_HIST_SPL_PIX_CNT (0x2e05) +#define VI_HIST_CHROMA_SUM (0x2e06) + ssize_t len = 0; + u32 hist_result[4]; + + if (hist_test_flag) { + hist_result[0] = READ_VCBUS_REG(VI_HIST_MAX_MIN); + hist_result[1] = READ_VCBUS_REG(VI_HIST_SPL_VAL); + hist_result[2] = READ_VCBUS_REG(VI_HIST_SPL_PIX_CNT); + hist_result[3] = READ_VCBUS_REG(VI_HIST_CHROMA_SUM); + + len += + sprintf(buf + len, "\n======time %d =====\n", + hist_print_count + 1); + len += + sprintf(buf + len, "hist_max_min: 0x%08x\n", + hist_result[0]); + len += + sprintf(buf + len, "hist_spl_val: 0x%08x\n", + hist_result[1]); + len += + sprintf(buf + len, "hist_spl_pix_cnt: 0x%08x\n", + hist_result[2]); + len += + sprintf(buf + len, "hist_chroma_sum: 0x%08x\n", + hist_result[3]); + msleep(50); + hist_print_count++; + } else { + len += + sprintf(buf + len, "no hist data\n"); + } + return len; +} + +static ssize_t hist_test_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ +#define VI_HIST_CTRL (0x2e00) +#define VI_HIST_H_START_END (0x2e01) +#define VI_HIST_V_START_END (0x2e02) +#define VI_HIST_PIC_SIZE (0x2e28) +#define VIU_EOTF_CTL (0x31d0) +#define XVYCC_LUT_CTL (0x3165) +#define XVYCC_INV_LUT_CTL (0x3164) +#define XVYCC_VD1_RGB_CTRST (0x3170) + int parsed[3]; + int frame_width = 0, frame_height = 0; + int pat_val = 0, canvas_width; + u32 hist_dst_w, hist_dst_h; + const struct vinfo_s *ginfo = get_current_vinfo(); + struct disp_info_s *layer = &glayer_info[0]; + + if (likely(parse_para(buf, 3, parsed) == 3)) { + frame_width = parsed[0]; + frame_height = parsed[1]; + pat_val = parsed[2]; + } + + if (cur_dispbuf + && (cur_dispbuf != &vf_local) + && (cur_dispbuf != &hist_test_vf)) + pat_val = 0; + if (!frame_width || !frame_height) + pat_val = 0; + + if (legacy_vpp) + pat_val = 0; + + if (pat_val > 0 && pat_val <= 0x3fffffff) { + if (!hist_test_flag) { + memset(&hist_test_vf, 0, sizeof(hist_test_vf)); + canvas_width = (frame_width + 31) & (~31); + if (!alloc_hist_test_buffer( + canvas_width * frame_height * 3)) { + hist_test_vf.canvas0Addr = + DISPLAY_CANVAS_BASE_INDEX + 5; + hist_test_vf.canvas1Addr = + DISPLAY_CANVAS_BASE_INDEX + 5; + canvas_config( + DISPLAY_CANVAS_BASE_INDEX + 5, + (unsigned int)hist_buffer_addr, + canvas_width * 3, + frame_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hist_test_vf.width = frame_width; + hist_test_vf.height = frame_height; + hist_test_vf.type = VIDTYPE_VIU_444 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | VIDTYPE_PIC; + /* indicate the vframe is a full range frame */ + hist_test_vf.signal_type = + /* HD default 709 limit */ + (1 << 29) /* video available */ + | (5 << 26) /* unspecified */ + | (1 << 25) /* full */ + | (1 << 24) /* color available */ + | (1 << 16) /* bt709 */ + | (1 << 8) /* bt709 */ + | (1 << 0); /* bt709 */ + hist_test_vf.duration_pulldown = 0; + hist_test_vf.index = 0; + hist_test_vf.pts = 0; + hist_test_vf.pts_us64 = 0; + hist_test_vf.ratio_control = 0; + hist_test_flag = true; + WRITE_VCBUS_REG(VIU_EOTF_CTL, 0); + WRITE_VCBUS_REG(XVYCC_LUT_CTL, 0); + WRITE_VCBUS_REG(XVYCC_INV_LUT_CTL, 0); + WRITE_VCBUS_REG(VPP_VADJ_CTRL, 0); + WRITE_VCBUS_REG(VPP_GAINOFF_CTRL0, 0); + WRITE_VCBUS_REG(VPP_VE_ENABLE_CTRL, 0); + WRITE_VCBUS_REG(XVYCC_VD1_RGB_CTRST, 0); + if (ginfo) { + if (ginfo->width > + (layer->layer_width + + layer->layer_left)) + hist_dst_w = + layer->layer_width + + layer->layer_left; + else + hist_dst_w = + ginfo->width; + if (ginfo->field_height > + (layer->layer_height + + layer->layer_top)) + hist_dst_h = + layer->layer_height + + layer->layer_top; + else + hist_dst_h = + ginfo->field_height; + WRITE_VCBUS_REG( + VI_HIST_H_START_END, + hist_dst_w & 0xfff); + WRITE_VCBUS_REG( + VI_HIST_V_START_END, + (hist_dst_h - 2) & 0xfff); + WRITE_VCBUS_REG( + VI_HIST_PIC_SIZE, + (ginfo->width & 0xfff) | + (ginfo->field_height << 16)); + WRITE_VCBUS_REG(VI_HIST_CTRL, 0x3803); + } else { + WRITE_VCBUS_REG( + VI_HIST_H_START_END, 0); + WRITE_VCBUS_REG( + VI_HIST_V_START_END, 0); + WRITE_VCBUS_REG( + VI_HIST_PIC_SIZE, + (ginfo->width & 0xfff) | + (ginfo->field_height << 16)); + WRITE_VCBUS_REG(VI_HIST_CTRL, 0x3801); + } + } + } + WRITE_VCBUS_REG(VPP_VD1_CLIP_MISC0, pat_val); + WRITE_VCBUS_REG(VPP_VD1_CLIP_MISC1, pat_val); + WRITE_VCBUS_REG(DOLBY_PATH_CTRL, 0x3f); + msleep(50); + hist_print_count = 0; + } else if (hist_test_flag) { + hist_test_flag = false; + msleep(50); + free_alloced_hist_test_buffer(); + WRITE_VCBUS_REG(VPP_VD1_CLIP_MISC0, 0x3fffffff); + WRITE_VCBUS_REG(VPP_VD1_CLIP_MISC1, 0); + WRITE_VCBUS_REG(DOLBY_PATH_CTRL, 0xf); + safe_disable_videolayer(); + } + return strnlen(buf, count); +} + +#ifdef VIDEO_PIP +int _videopip_set_disable(u32 val) +{ + if (val > VIDEO_DISABLE_FORNEXT) + return -EINVAL; + + disable_videopip = val; + + if (disable_videopip != VIDEO_DISABLE_NONE) { + DisableVideoLayer2(); + + if ((disable_videopip == VIDEO_DISABLE_FORNEXT) + && cur_pipbuf && (cur_pipbuf != &local_pip)) + pip_property_changed = 1; + try_free_keep_videopip(0); + } else { + if (cur_pipbuf && (cur_pipbuf != &local_pip)) + EnableVideoLayer2(); + } + + return 0; +} + +static ssize_t blackout_pip_policy_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", blackout_pip); +} + +static ssize_t blackout_pip_policy_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &blackout_pip); + if (r < 0) + return -EINVAL; + + return count; +} + +static ssize_t axis_pip_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + int x0, y0, x1, y1; + struct disp_info_s *layer = &glayer_info[1]; + + x0 = layer->layer_left; + y0 = layer->layer_top; + x1 = layer->layer_width + x0 - 1; + y1 = layer->layer_height + y0 - 1; + return snprintf(buf, 40, "%d %d %d %d\n", x0, y0, x1, y1); +} + +static ssize_t axis_pip_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[1]; + + mutex_lock(&video_module_mutex); + + set_video_window(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t crop_pip_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 t, l, b, r; + struct disp_info_s *layer = &glayer_info[1]; + + t = layer->crop_top; + l = layer->crop_left; + b = layer->crop_bottom; + r = layer->crop_right; + return snprintf(buf, 40, "%d %d %d %d\n", t, l, b, r); +} + +static ssize_t crop_pip_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[1]; + + mutex_lock(&video_module_mutex); + + set_video_crop(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t disable_videopip_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", disable_videopip); +} + +static ssize_t disable_videopip_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%s)\n", __func__, buf); + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + if (_videopip_set_disable(val) < 0) + return -EINVAL; + + return count; +} + +static ssize_t screen_mode_pip_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[1]; + static const char * const wide_str[] = { + "normal", "full stretch", "4-3", "16-9", "non-linear", + "normal-noscaleup", + "4-3 ignore", "4-3 letter box", "4-3 pan scan", "4-3 combined", + "16-9 ignore", "16-9 letter box", "16-9 pan scan", + "16-9 combined", "Custom AR", "AFD" + }; + + if (layer->wide_mode < ARRAY_SIZE(wide_str)) { + return sprintf(buf, "%d:%s\n", + layer->wide_mode, + wide_str[layer->wide_mode]); + } else + return 0; +} + +static ssize_t screen_mode_pip_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned long mode; + int ret = 0; + struct disp_info_s *layer = &glayer_info[1]; + + ret = kstrtoul(buf, 0, (unsigned long *)&mode); + if (ret < 0) + return -EINVAL; + + if ((mode < VIDEO_WIDEOPTION_MAX) + && (mode != layer->wide_mode)) { + layer->wide_mode = mode; + pip_property_changed = 1; + } + return count; +} + +static ssize_t videopip_loop_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", pip_loop); +} + +static ssize_t videopip_loop_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + pip_loop = val; + return count; +} + +static ssize_t pip_global_output_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", pip_global_output); +} + +static ssize_t pip_global_output_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &pip_global_output); + if (r < 0) + return -EINVAL; + + pr_info("%s(%d)\n", __func__, pip_global_output); + + return count; +} + +static ssize_t videopip_zorder_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[1]; + + return sprintf(buf, "%d\n", layer->zorder); +} + +static ssize_t videopip_zorder_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int zorder; + int ret = 0; + struct disp_info_s *layer = &glayer_info[1]; + + ret = kstrtoint(buf, 0, &zorder); + if (ret < 0) + return -EINVAL; + + if (zorder != layer->zorder) { + layer->zorder = zorder; + pip_property_changed = 1; + } + return count; +} + +static ssize_t videopip_state_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + ssize_t len = 0; + struct vppfilter_mode_s *vpp_filter = NULL; + + if (!curpip_frame_par) + return len; + vpp_filter = &curpip_frame_par->vpp_filter; + len += sprintf(buf + len, + "zoom2_start_x_lines:%u.zoom2_end_x_lines:%u.\n", + zoom2_start_x_lines, zoom2_end_x_lines); + len += sprintf(buf + len, + "zoom2_start_y_lines:%u.zoom2_end_y_lines:%u.\n", + zoom2_start_y_lines, zoom2_end_y_lines); + len += sprintf(buf + len, "frame parameters: pic_in_height %u.\n", + curpip_frame_par->VPP_pic_in_height_); + len += sprintf(buf + len, + "frame parameters: VPP_line_in_length_ %u.\n", + curpip_frame_par->VPP_line_in_length_); + len += sprintf(buf + len, "vscale_skip_count %u.\n", + curpip_frame_par->vscale_skip_count); + len += sprintf(buf + len, "hscale_skip_count %u.\n", + curpip_frame_par->hscale_skip_count); + len += sprintf(buf + len, "supscl_path %u.\n", + curpip_frame_par->supscl_path); + len += sprintf(buf + len, "supsc0_enable %u.\n", + curpip_frame_par->supsc0_enable); + len += sprintf(buf + len, "supsc1_enable %u.\n", + curpip_frame_par->supsc1_enable); + len += sprintf(buf + len, "supsc0_hori_ratio %u.\n", + curpip_frame_par->supsc0_hori_ratio); + len += sprintf(buf + len, "supsc1_hori_ratio %u.\n", + curpip_frame_par->supsc1_hori_ratio); + len += sprintf(buf + len, "supsc0_vert_ratio %u.\n", + curpip_frame_par->supsc0_vert_ratio); + len += sprintf(buf + len, "supsc1_vert_ratio %u.\n", + curpip_frame_par->supsc1_vert_ratio); + len += sprintf(buf + len, "spsc0_h_in %u.\n", + curpip_frame_par->spsc0_h_in); + len += sprintf(buf + len, "spsc1_h_in %u.\n", + curpip_frame_par->spsc1_h_in); + len += sprintf(buf + len, "spsc0_w_in %u.\n", + curpip_frame_par->spsc0_w_in); + len += sprintf(buf + len, "spsc1_w_in %u.\n", + curpip_frame_par->spsc1_w_in); + len += sprintf(buf + len, "video_input_w %u.\n", + curpip_frame_par->video_input_w); + len += sprintf(buf + len, "video_input_h %u.\n", + curpip_frame_par->video_input_h); + len += sprintf(buf + len, "clk_in_pps %u.\n", + curpip_frame_par->clk_in_pps); + len += + sprintf(buf + len, "hscale phase step 0x%x.\n", + vpp_filter->vpp_hsc_start_phase_step); + len += + sprintf(buf + len, "vscale phase step 0x%x.\n", + vpp_filter->vpp_vsc_start_phase_step); + len += + sprintf(buf + len, "pps pre hsc enable %d.\n", + vpp_filter->vpp_pre_hsc_en); + len += + sprintf(buf + len, "pps pre vsc enable %d.\n", + vpp_filter->vpp_pre_vsc_en); + len += + sprintf(buf + len, "hscale filter coef %d.\n", + vpp_filter->vpp_horz_filter); + len += + sprintf(buf + len, "vscale filter coef %d.\n", + vpp_filter->vpp_vert_filter); + len += + sprintf(buf + len, "vpp_vert_chroma_filter_en %d.\n", + vpp_filter->vpp_vert_chroma_filter_en); + len += + sprintf(buf + len, "post_blend_vd_h_start 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_h_start_); + len += + sprintf(buf + len, "post_blend_vd_h_end 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_h_end_); + len += + sprintf(buf + len, "post_blend_vd_v_start 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_v_start_); + len += + sprintf(buf + len, "post_blend_vd_v_end 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_v_end_); + len += + sprintf(buf + len, "VPP_hd_start_lines_ 0x%x.\n", + curpip_frame_par->VPP_hd_start_lines_); + len += + sprintf(buf + len, "VPP_hd_end_lines_ 0x%x.\n", + curpip_frame_par->VPP_hd_end_lines_); + len += + sprintf(buf + len, "VPP_vd_start_lines_ 0x%x.\n", + curpip_frame_par->VPP_vd_start_lines_); + len += + sprintf(buf + len, "VPP_vd_end_lines_ 0x%x.\n", + curpip_frame_par->VPP_vd_end_lines_); + len += + sprintf(buf + len, "VPP_hsc_startp 0x%x.\n", + curpip_frame_par->VPP_hsc_startp); + len += + sprintf(buf + len, "VPP_hsc_endp 0x%x.\n", + curpip_frame_par->VPP_hsc_endp); + len += + sprintf(buf + len, "VPP_vsc_startp 0x%x.\n", + curpip_frame_par->VPP_vsc_startp); + len += + sprintf(buf + len, "VPP_vsc_endp 0x%x.\n", + curpip_frame_par->VPP_vsc_endp); + return len; +} + +#endif + +static CLASS_ATTR_RW(axis); +static CLASS_ATTR_RW(crop); +static CLASS_ATTR_RW(sr); +static CLASS_ATTR_RW(global_offset); +static CLASS_ATTR_RW(screen_mode); +static CLASS_ATTR_RW(blackout_policy); +static CLASS_ATTR_RW(blackout_pip_policy); +static CLASS_ATTR_RW(video_seek_flag); +static CLASS_ATTR_RW(disable_video); +static CLASS_ATTR_RW(video_global_output); +static CLASS_ATTR_RW(hold_video); +static CLASS_ATTR_RW(zoom); +static CLASS_ATTR_RW(brightness); +static CLASS_ATTR_RW(contrast); +static CLASS_ATTR_RW(vpp_brightness); +static CLASS_ATTR_RW(vpp_contrast); +static CLASS_ATTR_RW(saturation); +static CLASS_ATTR_RW(vpp_saturation_hue); +static CLASS_ATTR_RW(test_screen); +static CLASS_ATTR_RW(rgb_screen); +static CLASS_ATTR_RW(file_name); +static CLASS_ATTR_RW(debugflags); +static CLASS_ATTR_RW(trickmode_duration); +static CLASS_ATTR_RW(nonlinear_factor); +static CLASS_ATTR_RW(freerun_mode); +static CLASS_ATTR_RW(video_speed_check_h_w); +static CLASS_ATTR_RW(threedim_mode); +static CLASS_ATTR_RW(vsync_pts_inc_upint); +static CLASS_ATTR_RW(vsync_slow_factor); +static CLASS_ATTR_RW(angle); +static CLASS_ATTR_WO(stereo_scaler); +static CLASS_ATTR_RW(show_first_frame_nosync); +static CLASS_ATTR_WO(show_first_picture); +static CLASS_ATTR_RW(slowsync_repeat_enable); +static CLASS_ATTR_WO(free_keep_buffer); +static CLASS_ATTR_WO(free_cma_buffer); +#ifdef CONFIG_AM_VOUT +static CLASS_ATTR_RO(device_resolution); +#endif +#ifdef PTS_TRACE_DEBUG +static CLASS_ATTR_RO(pts_trace); +#endif +static CLASS_ATTR_RW(video_inuse); +static CLASS_ATTR_RW(video_zorder); +static CLASS_ATTR_RW(black_threshold); +static CLASS_ATTR_RW(hist_test); +static CLASS_ATTR_RO(frame_addr); +static CLASS_ATTR_RO(frame_canvas_width); +static CLASS_ATTR_RO(frame_canvas_height); +static CLASS_ATTR_RO(frame_width); +static CLASS_ATTR_RO(frame_height); +static CLASS_ATTR_RO(frame_format); +static CLASS_ATTR_RO(frame_aspect_ratio); +static CLASS_ATTR_RO(frame_rate); +static CLASS_ATTR_RO(vframe_states); +static CLASS_ATTR_RO(video_state); +static CLASS_ATTR_RO(fps_info); +static CLASS_ATTR_RO(vframe_ready_cnt); +static CLASS_ATTR_RO(video_layer1_state); +static CLASS_ATTR_RO(pic_mode_info); +#ifdef VIDEO_PIP +static CLASS_ATTR_RW(axis_pip); +static CLASS_ATTR_RW(crop_pip); +static CLASS_ATTR_RW(disable_videopip); +static CLASS_ATTR_RW(screen_mode_pip); +static CLASS_ATTR_RW(videopip_loop); +static CLASS_ATTR_RW(pip_global_output); +static CLASS_ATTR_RW(videopip_zorder); +static CLASS_ATTR_RO(videopip_state); +#endif + +static struct attribute *amvideo_class_attrs[] = { + &class_attr_axis.attr, + &class_attr_crop.attr, + &class_attr_sr.attr, + &class_attr_global_offset.attr, + &class_attr_screen_mode.attr, + &class_attr_blackout_policy.attr, + &class_attr_blackout_pip_policy.attr, + &class_attr_video_seek_flag.attr, + &class_attr_disable_video.attr, + &class_attr_video_global_output.attr, + &class_attr_hold_video.attr, + &class_attr_zoom.attr, + &class_attr_brightness.attr, + &class_attr_contrast.attr, + &class_attr_vpp_brightness.attr, + &class_attr_vpp_contrast.attr, + &class_attr_saturation.attr, + &class_attr_vpp_saturation_hue.attr, + &class_attr_test_screen.attr, + &class_attr_rgb_screen.attr, + &class_attr_file_name.attr, + &class_attr_debugflags.attr, + &class_attr_trickmode_duration.attr, + &class_attr_nonlinear_factor.attr, + &class_attr_freerun_mode.attr, + &class_attr_video_speed_check_h_w.attr, + &class_attr_threedim_mode.attr, + &class_attr_vsync_pts_inc_upint.attr, + &class_attr_vsync_slow_factor.attr, + &class_attr_angle.attr, + &class_attr_stereo_scaler.attr, + &class_attr_show_first_frame_nosync.attr, + &class_attr_show_first_picture.attr, + &class_attr_slowsync_repeat_enable.attr, + &class_attr_free_keep_buffer.attr, + &class_attr_free_cma_buffer.attr, +#ifdef CONFIG_AM_VOUT + &class_attr_device_resolution.attr, +#endif +#ifdef PTS_TRACE_DEBUG + &class_attr_pts_trace.attr, +#endif + &class_attr_video_inuse.attr, + &class_attr_video_zorder.attr, + &class_attr_black_threshold.attr, + &class_attr_hist_test.attr, + &class_attr_frame_addr.attr, + &class_attr_frame_canvas_width.attr, + &class_attr_frame_canvas_height.attr, + &class_attr_frame_width.attr, + &class_attr_frame_height.attr, + &class_attr_frame_format.attr, + &class_attr_frame_aspect_ratio.attr, + &class_attr_frame_rate.attr, + &class_attr_vframe_states.attr, + &class_attr_video_state.attr, + &class_attr_fps_info.attr, + &class_attr_vframe_ready_cnt.attr, + &class_attr_video_layer1_state.attr, + &class_attr_pic_mode_info.attr, +#ifdef VIDEO_PIP + &class_attr_axis_pip.attr, + &class_attr_crop_pip.attr, + &class_attr_disable_videopip.attr, + &class_attr_screen_mode_pip.attr, + &class_attr_videopip_loop.attr, + &class_attr_pip_global_output.attr, + &class_attr_videopip_zorder.attr, + &class_attr_videopip_state.attr, +#endif + + NULL +}; + +ATTRIBUTE_GROUPS(amvideo_class); + +static struct class amvideo_class = { + .name = AMVIDEO_CLASS_NAME, + .class_groups = amvideo_class_groups, +}; + +static struct attribute *amvideo_poll_class_attrs[] = { + &class_attr_frame_width.attr, + &class_attr_frame_height.attr, + &class_attr_vframe_states.attr, + &class_attr_video_state.attr, + NULL +}; +ATTRIBUTE_GROUPS(amvideo_poll_class); + +static struct class amvideo_poll_class = { + .name = AMVIDEO_POLL_CLASS_NAME, + .class_groups = amvideo_poll_class_groups, +}; + +#ifdef TV_REVERSE +static int __init vpp_axis_reverse(char *str) +{ + unsigned char *ptr = str; + + pr_info("%s: bootargs is %s\n", __func__, str); + if (strstr(ptr, "1")) + reverse = true; + else + reverse = false; + + return 0; +} + +__setup("video_reverse=", vpp_axis_reverse); +#endif + +struct vframe_s *get_cur_dispbuf(void) +{ + return cur_dispbuf; +} + +#ifdef CONFIG_AM_VOUT +int vout_notify_callback(struct notifier_block *block, unsigned long cmd, + void *para) +{ + const struct vinfo_s *info; + ulong flags; + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + if (cur_dev != &video_dev[0]) + return 0; +#endif + switch (cmd) { + case VOUT_EVENT_MODE_CHANGE: + info = get_current_vinfo(); + spin_lock_irqsave(&lock, flags); + vinfo = info; + /* pre-calculate vsync_pts_inc in 90k unit */ + vsync_pts_inc = 90000 * vinfo->sync_duration_den / + vinfo->sync_duration_num; + vsync_pts_inc_scale = vinfo->sync_duration_den; + vsync_pts_inc_scale_base = vinfo->sync_duration_num; + spin_unlock_irqrestore(&lock, flags); + new_vmode = vinfo->mode; + break; + case VOUT_EVENT_OSD_PREBLEND_ENABLE: + break; + case VOUT_EVENT_OSD_DISP_AXIS: + break; + } + return 0; +} + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 +int vout2_notify_callback(struct notifier_block *block, unsigned long cmd, + void *para) +{ + const struct vinfo_s *info; + ulong flags; + + if (cur_dev != &video_dev[1]) + return 0; + + switch (cmd) { + case VOUT_EVENT_MODE_CHANGE: + info = get_current_vinfo2(); + spin_lock_irqsave(&lock, flags); + vinfo = info; + /* pre-calculate vsync_pts_inc in 90k unit */ + vsync_pts_inc = 90000 * vinfo->sync_duration_den / + vinfo->sync_duration_num; + vsync_pts_inc_scale = vinfo->sync_duration_den; + vsync_pts_inc_scale_base = vinfo->sync_duration_num; + spin_unlock_irqrestore(&lock, flags); + break; + case VOUT_EVENT_OSD_PREBLEND_ENABLE: + break; + case VOUT_EVENT_OSD_DISP_AXIS: + break; + } + return 0; +} +#endif + + +static struct notifier_block vout_notifier = { + .notifier_call = vout_notify_callback, +}; + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 +static struct notifier_block vout2_notifier = { + .notifier_call = vout2_notify_callback, +}; +#endif + + +static void vout_hook(void) +{ + vout_register_client(&vout_notifier); + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + vout2_register_client(&vout2_notifier); +#endif + + vinfo = get_current_vinfo(); + + if (!vinfo) { +#if DEBUG_TMP + set_current_vmode(VMODE_720P); +#endif + vinfo = get_current_vinfo(); + } + + if (vinfo) { + vsync_pts_inc = 90000 * vinfo->sync_duration_den / + vinfo->sync_duration_num; + vsync_pts_inc_scale = vinfo->sync_duration_den; + vsync_pts_inc_scale_base = vinfo->sync_duration_num; + old_vmode = new_vmode = vinfo->mode; + } +#ifdef CONFIG_AM_VIDEO_LOG + if (vinfo) { + amlog_mask(LOG_MASK_VINFO, "vinfo = %p\n", vinfo); + amlog_mask(LOG_MASK_VINFO, "display platform %s:\n", + vinfo->name); + amlog_mask(LOG_MASK_VINFO, "\tresolution %d x %d\n", + vinfo->width, vinfo->height); + amlog_mask(LOG_MASK_VINFO, "\taspect ratio %d : %d\n", + vinfo->aspect_ratio_num, vinfo->aspect_ratio_den); + amlog_mask(LOG_MASK_VINFO, "\tsync duration %d : %d\n", + vinfo->sync_duration_num, vinfo->sync_duration_den); + } +#endif +} +#endif + +static int amvideo_notify_callback( + struct notifier_block *block, + unsigned long cmd, + void *para) +{ + u32 *p, val; + + switch (cmd) { + case AMVIDEO_UPDATE_OSD_MODE: + p = (u32 *)para; + if (!update_osd_vpp_misc) + osd_vpp_misc_mask = p[1]; + val = osd_vpp_misc + & (~osd_vpp_misc_mask); + val |= (p[0] & osd_vpp_misc_mask); + osd_vpp_misc = val; + if (!update_osd_vpp_misc) + update_osd_vpp_misc = true; + break; + default: + break; + } + return 0; +} + +static struct notifier_block amvideo_notifier = { + .notifier_call = amvideo_notify_callback, +}; + +static RAW_NOTIFIER_HEAD(amvideo_notifier_list); +int amvideo_register_client(struct notifier_block *nb) +{ + return raw_notifier_chain_register(&amvideo_notifier_list, nb); +} +EXPORT_SYMBOL(amvideo_register_client); + +int amvideo_unregister_client(struct notifier_block *nb) +{ + return raw_notifier_chain_unregister(&amvideo_notifier_list, nb); +} +EXPORT_SYMBOL(amvideo_unregister_client); + +int amvideo_notifier_call_chain(unsigned long val, void *v) +{ + return raw_notifier_call_chain(&amvideo_notifier_list, val, v); +} +EXPORT_SYMBOL_GPL(amvideo_notifier_call_chain); + +static void do_vpu_delay_work(struct work_struct *work) +{ + unsigned long flags; + unsigned int r; + +#if DEBUG_TMP + if (vpu_delay_work_flag & VPU_VIDEO_LAYER1_CHANGED) { + vpu_delay_work_flag &= ~VPU_VIDEO_LAYER1_CHANGED; + + switch_set_state(&video1_state_sdev, !!video_enabled); + } +#endif + spin_lock_irqsave(&delay_work_lock, flags); + + if (vpu_delay_work_flag & VPU_DELAYWORK_VPU_CLK) { + vpu_delay_work_flag &= ~VPU_DELAYWORK_VPU_CLK; + + spin_unlock_irqrestore(&delay_work_lock, flags); + + if (vpu_clk_level > 0) + vpu_vmod_clk_request(360000000, VPU_VIU_VD1); + else + vpu_vmod_clk_release(VPU_VIU_VD1); + + spin_lock_irqsave(&delay_work_lock, flags); + } + + 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; + + vpu_vmod_mem_pd_switch( + VPU_VIU_VD1, + VPU_MEM_POWER_DOWN); + vpu_vmod_mem_pd_switch( + VPU_AFBC_DEC, + VPU_MEM_POWER_DOWN); + vpu_vmod_mem_pd_switch( + VPU_DI_POST, + VPU_MEM_POWER_DOWN); + if (!legacy_vpp) + vpu_vmod_mem_pd_switch( + VPU_VD1_SCALE, + 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; + + vpu_vmod_mem_pd_switch( + VPU_VIU_VD2, + VPU_MEM_POWER_DOWN); + vpu_vmod_mem_pd_switch( + VPU_AFBC_DEC1, + VPU_MEM_POWER_DOWN); + if (!legacy_vpp) + vpu_vmod_mem_pd_switch( + VPU_VD2_SCALE, + VPU_MEM_POWER_DOWN); + } + + if ((vpu_delay_work_flag & + VPU_DELAYWORK_MEM_POWER_OFF_PROT) + && ((r & VPP_VD1_PREBLEND) == 0)) { + vpu_delay_work_flag &= + ~VPU_DELAYWORK_MEM_POWER_OFF_PROT; + } + } + } + + spin_unlock_irqrestore(&delay_work_lock, flags); +} + +/*********************************************************/ +struct device *get_video_device(void) +{ + return amvideo_dev; +} + +static int __init video_early_init(void) +{ + /* todo: move this to clock tree, enable VPU clock */ + /* WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,*/ + /*(1<<9) | (1<<8) | (3)); // fclk_div3/4 = ~200M */ + /* WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,*/ + /*(3<<9) | (1<<8) | (0)); // fclk_div7/1 = 364M*/ + /*moved to vpu.c, default config by dts */ + + u32 cur_hold_line; + + 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( + VD1_IF0_LUMA_FIFO_SIZE + cur_dev->viu_off, 0x180); + WRITE_VCBUS_REG( + VD2_IF0_LUMA_FIFO_SIZE + cur_dev->viu_off, 0x180); + } + +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x800, + VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); + /* + *WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 1, 12, 2); + *select vdisp_mmc_arb for VIU2_OSD1 request + */ + WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 2, 12, 2); + /* select vdin_mmc_arb for VIU2_OSD1 request */ +#endif + /* 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 */ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) + vpu_vmod_mem_pd_switch(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 (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + /* force bypass dolby for TL1, no dolby function */ + if (is_meson_tl1_cpu()) + WRITE_VCBUS_REG_BITS( + DOLBY_PATH_CTRL, 0xf, 0, 6); + /* disable latch for sr core0/1 scaler */ + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); + WRITE_VCBUS_REG_BITS( + SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); + return 0; +} + +static struct mconfig video_configs[] = { + MC_PI32("pause_one_3d_fl_frame", &pause_one_3d_fl_frame), + MC_PI32("debug_flag", &debug_flag), + MC_PU32("force_3d_scaler", &force_3d_scaler), + MC_PU32("video_3d_format", &video_3d_format), + MC_PI32("vsync_enter_line_max", &vsync_enter_line_max), + MC_PI32("vsync_exit_line_max", &vsync_exit_line_max), +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + MC_PI32("vsync_rdma_line_max", &vsync_rdma_line_max), +#endif + MC_PU32("underflow", &underflow), + MC_PU32("next_peek_underflow", &next_peek_underflow), + MC_PU32("smooth_sync_enable", &smooth_sync_enable), + MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo), +#ifdef CONFIG_AM_VIDEO2 + MC_PI32("video_play_clone_rate", &video_play_clone_rate), + MC_PI32("android_clone_rate", &android_clone_rate), + MC_PI32("video_play_clone_rate", &video_play_clone_rate), + MC_PI32("android_clone_rate", &android_clone_rate), + MC_PI32("noneseamless_play_clone_rate", &noneseamless_play_clone_rate), +#endif + MC_PU32("smooth_sync_enable", &smooth_sync_enable), + MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo), + MC_PI32("cur_dev_idx", &cur_dev_idx), + MC_PU32("new_frame_count", &new_frame_count), + MC_PU32("omx_pts", &omx_pts), + MC_PU32("omx_pts_set_index", &omx_pts_set_index), + MC_PBOOL("omx_run", &omx_run), + MC_PU32("omx_version", &omx_version), + MC_PU32("omx_info", &omx_info), + MC_PI32("omx_need_drop_frame_num", &omx_need_drop_frame_num), + MC_PBOOL("omx_drop_done", &omx_drop_done), + MC_PI32("omx_pts_interval_upper", &omx_pts_interval_upper), + MC_PI32("omx_pts_interval_lower", &omx_pts_interval_lower), + MC_PBOOL("bypass_pps", &bypass_pps), + MC_PBOOL("platform_type", &platform_type), + MC_PU32("process_3d_type", &process_3d_type), + MC_PU32("omx_pts", &omx_pts), + MC_PU32("framepacking_support", &framepacking_support), + MC_PU32("framepacking_width", &framepacking_width), + MC_PU32("framepacking_height", &framepacking_height), + MC_PU32("framepacking_blank", &framepacking_blank), + MC_PU32("video_seek_flag", &video_seek_flag), + MC_PU32("slowsync_repeat_enable", &slowsync_repeat_enable), + MC_PU32("toggle_count", &toggle_count), + MC_PBOOL("show_first_frame_nosync", &show_first_frame_nosync), +#ifdef TV_REVERSE + MC_PBOOL("reverse", &reverse), +#endif +}; + +#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND +static void video_early_suspend(struct early_suspend *h) +{ + DisableVideoLayer(); + DisableVideoLayer2(); + pr_info("%s ok\n", __func__); +} + +static void video_late_resume(struct early_suspend *h) +{ + pr_info("%s ok\n", __func__); +}; + +static struct early_suspend video_early_suspend_handler = { + .suspend = video_early_suspend, + .resume = video_late_resume, +}; +#endif + +static int amvideom_probe(struct platform_device *pdev) +{ + int ret = 0; + + video_early_init(); + + DisableVideoLayer(); + DisableVideoLayer2(); + + /* get interrupt resource */ + video_vsync = platform_get_irq_byname(pdev, "vsync"); + if (video_vsync == -ENXIO) { + pr_info("cannot get amvideom irq resource\n"); + + return video_vsync; + } + + pr_info("amvideom vsync irq: %d\n", video_vsync); + +#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND + register_early_suspend(&video_early_suspend_handler); +#endif + return ret; +} + +static int amvideom_remove(struct platform_device *pdev) +{ +#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND + unregister_early_suspend(&video_early_suspend_handler); +#endif + return 0; +} + +static const struct of_device_id amlogic_amvideom_dt_match[] = { + { + .compatible = "amlogic, amvideom", + }, + {}, +}; + +static struct platform_driver amvideom_driver = { + .probe = amvideom_probe, + .remove = amvideom_remove, + .driver = { + .name = "amvideom", + .of_match_table = amlogic_amvideom_dt_match, + }, +}; + +static int __init video_init(void) +{ + int r = 0, i; + /* + *#ifdef CONFIG_ARCH_MESON1 + *ulong clk = clk_get_rate(clk_get_sys("clk_other_pll", NULL)); + *#elif !defined(CONFIG_ARCH_MESON3) && !defined(CONFIG_ARCH_MESON6) + *ulong clk = clk_get_rate(clk_get_sys("clk_misc_pll", NULL)); + *#endif + */ + +#ifdef CONFIG_ARCH_MESON1 + no to here ulong clk = + clk_get_rate(clk_get_sys("clk_other_pll", NULL)); +#elif defined(CONFIG_ARCH_MESON2) + not to here ulong clk = + clk_get_rate(clk_get_sys("clk_misc_pll", NULL)); +#endif + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + cur_dev->viu_off = 0x3200 - 0x1a50; + legacy_vpp = false; + } + if (platform_driver_register(&amvideom_driver)) { + pr_info("failed to amvideom driver!\n"); + return -ENODEV; + } + + /* check super scaler support status */ + vpp_super_scaler_support(); + /* adaptive config bypass ratio */ + vpp_bypass_ratio_config(); + +#ifndef CONFIG_AM_VIDEO2 + /*DisableVPP2VideoLayer();*/ +#endif + + cur_dispbuf = NULL; + cur_dispbuf2 = NULL; + amvideo_register_client(&amvideo_notifier); + +#ifdef FIQ_VSYNC + /* enable fiq bridge */ + vsync_fiq_bridge.handle = vsync_bridge_isr; + vsync_fiq_bridge.key = (u32) vsync_bridge_isr; + vsync_fiq_bridge.name = "vsync_bridge_isr"; + + r = register_fiq_bridge_handle(&vsync_fiq_bridge); + + if (r) { + amlog_level(LOG_LEVEL_ERROR, + "video fiq bridge register error.\n"); + r = -ENOENT; + goto err0; + } +#endif + + /* sysfs node creation */ + r = class_register(&amvideo_poll_class); + if (r) { + amlog_level(LOG_LEVEL_ERROR, "create video_poll class fail.\n"); +#ifdef FIQ_VSYNC + free_irq(BRIDGE_IRQ, (void *)video_dev_id); +#else + free_irq(INT_VIU_VSYNC, (void *)video_dev_id); +#endif + goto err1; + } + + r = class_register(&amvideo_class); + if (r) { + amlog_level(LOG_LEVEL_ERROR, "create video class fail.\n"); +#ifdef FIQ_VSYNC + free_irq(BRIDGE_IRQ, (void *)video_dev_id); +#else + free_irq(INT_VIU_VSYNC, (void *)video_dev_id); +#endif + goto err1; + } + + /* create video device */ + r = register_chrdev(AMVIDEO_MAJOR, "amvideo", &amvideo_fops); + if (r < 0) { + amlog_level(LOG_LEVEL_ERROR, + "Can't register major for amvideo device\n"); + goto err2; + } + + r = register_chrdev(0, "amvideo_poll", &amvideo_poll_fops); + if (r < 0) { + amlog_level(LOG_LEVEL_ERROR, + "Can't register major for amvideo_poll device\n"); + goto err3; + } + + amvideo_poll_major = r; + + amvideo_dev = device_create(&amvideo_class, NULL, + MKDEV(AMVIDEO_MAJOR, 0), NULL, DEVICE_NAME); + + if (IS_ERR(amvideo_dev)) { + amlog_level(LOG_LEVEL_ERROR, "Can't create amvideo device\n"); + goto err4; + } + + amvideo_poll_dev = device_create(&amvideo_poll_class, NULL, + MKDEV(amvideo_poll_major, 0), NULL, "amvideo_poll"); + + if (IS_ERR(amvideo_poll_dev)) { + amlog_level(LOG_LEVEL_ERROR, + "Can't create amvideo_poll device\n"); + goto err5; + } + + /* make vd1 below vd2 */ + for (i = 0; i < MAX_VD_LAYERS; i++) { + 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; + 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; + } else if (is_meson_tm2_cpu()) { + glayer_info[i].afbc_support = + (i == 0) ? true : false; + glayer_info[i].pps_support = true; + } else { + glayer_info[i].afbc_support = true; + glayer_info[i].pps_support = true; + } + } + + if (legacy_vpp) + layer_cap = + LAYER1_AFBC | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else if (is_meson_tl1_cpu()) + layer_cap = + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else if (is_meson_tm2_cpu()) + layer_cap = + LAYER1_SCALER | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else + layer_cap = + LAYER1_AFBC | + LAYER1_SCALER | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + + init_waitqueue_head(&amvideo_trick_wait); + init_waitqueue_head(&amvideo_sizechange_wait); + + INIT_WORK(&vpu_delay_work, do_vpu_delay_work); + +#ifdef CONFIG_AM_VOUT + vout_hook(); +#endif + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + dispbuf_to_put_num = DISPBUF_TO_PUT_MAX; + while (dispbuf_to_put_num > 0) { + dispbuf_to_put_num--; + dispbuf_to_put[dispbuf_to_put_num] = NULL; + } + + disp_canvas[0][0] = + (disp_canvas_index[0][2] << 16) | (disp_canvas_index[0][1] << 8) | + disp_canvas_index[0][0]; + disp_canvas[0][1] = + (disp_canvas_index[0][5] << 16) | (disp_canvas_index[0][4] << 8) | + disp_canvas_index[0][3]; + + disp_canvas[1][0] = + (disp_canvas_index[1][2] << 16) | (disp_canvas_index[1][1] << 8) | + disp_canvas_index[1][0]; + disp_canvas[1][1] = + (disp_canvas_index[1][5] << 16) | (disp_canvas_index[1][4] << 8) | + disp_canvas_index[1][3]; +#else + + disp_canvas[0] = + (disp_canvas_index[2] << 16) | (disp_canvas_index[1] << 8) | + disp_canvas_index[0]; + disp_canvas[1] = + (disp_canvas_index[5] << 16) | (disp_canvas_index[4] << 8) | + disp_canvas_index[3]; +#endif + + vsync_fiq_up(); +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + vsync2_fiq_up(); +#endif + + vf_receiver_init(&video_vf_recv, RECEIVER_NAME, &video_vf_receiver, + NULL); + vf_reg_receiver(&video_vf_recv); + +#ifdef VIDEO_PIP + vf_receiver_init( + &videopip_vf_recv, RECEIVERPIP_NAME, + &videopip_vf_receiver, NULL); + vf_reg_receiver(&videopip_vf_recv); +#endif + +#if DEBUG_TMP + switch_dev_register(&video1_state_sdev); + switch_set_state(&video1_state_sdev, 0); +#endif + video_keeper_init(); +#ifdef CONFIG_AM_VIDEO2 + set_clone_frame_rate(android_clone_rate, 0); +#endif + REG_PATH_CONFIGS("media.video", video_configs); + video_debugfs_init(); + return 0; + err5: + device_destroy(&amvideo_class, MKDEV(AMVIDEO_MAJOR, 0)); + err4: + unregister_chrdev(amvideo_poll_major, "amvideo_poll"); + err3: + unregister_chrdev(AMVIDEO_MAJOR, DEVICE_NAME); + + err2: +#ifdef FIQ_VSYNC + unregister_fiq_bridge_handle(&vsync_fiq_bridge); +#endif + class_unregister(&amvideo_class); + err1: + class_unregister(&amvideo_poll_class); +#ifdef FIQ_VSYNC + err0: +#endif + amvideo_unregister_client(&amvideo_notifier); + platform_driver_unregister(&amvideom_driver); + + return r; +} + + +static void __exit video_exit(void) +{ + video_debugfs_exit(); + vf_unreg_receiver(&video_vf_recv); + +#ifdef VIDEO_PIP + vf_unreg_receiver(&videopip_vf_recv); +#endif + DisableVideoLayer(); + DisableVideoLayer2(); + + vsync_fiq_down(); +#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 + vsync2_fiq_down(); +#endif + device_destroy(&amvideo_class, MKDEV(AMVIDEO_MAJOR, 0)); + device_destroy(&amvideo_poll_class, MKDEV(amvideo_poll_major, 0)); + + unregister_chrdev(AMVIDEO_MAJOR, DEVICE_NAME); + unregister_chrdev(amvideo_poll_major, "amvideo_poll"); + +#ifdef FIQ_VSYNC + unregister_fiq_bridge_handle(&vsync_fiq_bridge); +#endif + + class_unregister(&amvideo_class); + class_unregister(&amvideo_poll_class); + amvideo_unregister_client(&amvideo_notifier); +} + + + +MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); +module_param(debug_flag, uint, 0664); + +#ifdef TV_3D_FUNCTION_OPEN +MODULE_PARM_DESC(force_3d_scaler, "\n force_3d_scaler\n"); +module_param(force_3d_scaler, uint, 0664); + +MODULE_PARM_DESC(video_3d_format, "\n video_3d_format\n"); +module_param(video_3d_format, uint, 0664); + +#endif + +MODULE_PARM_DESC(vsync_enter_line_max, "\n vsync_enter_line_max\n"); +module_param(vsync_enter_line_max, uint, 0664); + +MODULE_PARM_DESC(vsync_exit_line_max, "\n vsync_exit_line_max\n"); +module_param(vsync_exit_line_max, uint, 0664); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +MODULE_PARM_DESC(vsync_rdma_line_max, "\n vsync_rdma_line_max\n"); +module_param(vsync_rdma_line_max, uint, 0664); +#endif + +module_param(underflow, uint, 0664); +MODULE_PARM_DESC(underflow, "\n Underflow count\n"); + +module_param(next_peek_underflow, uint, 0664); +MODULE_PARM_DESC(skip, "\n Underflow count\n"); + +module_param(step_enable, uint, 0664); +MODULE_PARM_DESC(step_enable, "\n step_enable\n"); + +module_param(step_flag, uint, 0664); +MODULE_PARM_DESC(step_flag, "\n step_flag\n"); + +/*arch_initcall(video_early_init);*/ + +module_init(video_init); +module_exit(video_exit); + +MODULE_PARM_DESC(smooth_sync_enable, "\n smooth_sync_enable\n"); +module_param(smooth_sync_enable, uint, 0664); + +MODULE_PARM_DESC(hdmi_in_onvideo, "\n hdmi_in_onvideo\n"); +module_param(hdmi_in_onvideo, uint, 0664); + +#ifdef CONFIG_AM_VIDEO2 +MODULE_PARM_DESC(video_play_clone_rate, "\n video_play_clone_rate\n"); +module_param(video_play_clone_rate, uint, 0664); + +MODULE_PARM_DESC(android_clone_rate, "\n android_clone_rate\n"); +module_param(android_clone_rate, uint, 0664); + +MODULE_PARM_DESC(noneseamless_play_clone_rate, + "\n noneseamless_play_clone_rate\n"); +module_param(noneseamless_play_clone_rate, uint, 0664); + +#endif +MODULE_PARM_DESC(vsync_count, "\n vsync_count\n"); +module_param(vsync_count, uint, 0664); + + +MODULE_PARM_DESC(cur_dev_idx, "\n cur_dev_idx\n"); +module_param(cur_dev_idx, uint, 0664); + +MODULE_PARM_DESC(new_frame_count, "\n new_frame_count\n"); +module_param(new_frame_count, uint, 0664); + +MODULE_PARM_DESC(first_frame_toggled, "\n first_frame_toggled\n"); +module_param(first_frame_toggled, uint, 0664); + +MODULE_PARM_DESC(omx_pts, "\n omx_pts\n"); +module_param(omx_pts, uint, 0664); + +MODULE_PARM_DESC(omx_run, "\n omx_run\n"); +module_param(omx_run, bool, 0664); + +MODULE_PARM_DESC(omx_pts_set_index, "\n omx_pts_set_index\n"); +module_param(omx_pts_set_index, uint, 0664); + +MODULE_PARM_DESC(omx_version, "\n omx_version\n"); +module_param(omx_version, uint, 0664); + +MODULE_PARM_DESC(omx_info, "\n omx_info\n"); +module_param(omx_info, uint, 0664); + +MODULE_PARM_DESC(omx_need_drop_frame_num, "\n omx_need_drop_frame_num\n"); +module_param(omx_need_drop_frame_num, int, 0664); + +MODULE_PARM_DESC(omx_drop_done, "\n omx_drop_done\n"); +module_param(omx_drop_done, bool, 0664); + +MODULE_PARM_DESC(omx_pts_interval_upper, "\n omx_pts_interval\n"); +module_param(omx_pts_interval_upper, int, 0664); + +MODULE_PARM_DESC(omx_pts_interval_lower, "\n omx_pts_interval\n"); +module_param(omx_pts_interval_lower, int, 0664); + +MODULE_PARM_DESC(drop_frame_count, "\n drop_frame_count\n"); +module_param(drop_frame_count, int, 0664); + +MODULE_PARM_DESC(receive_frame_count, "\n receive_frame_count\n"); +module_param(receive_frame_count, int, 0664); + +MODULE_PARM_DESC(display_frame_count, "\n display_frame_count\n"); +module_param(display_frame_count, int, 0664); + +module_param(frame_detect_time, uint, 0664); +MODULE_PARM_DESC(frame_detect_time, "\n frame_detect_time\n"); + +module_param(frame_detect_flag, uint, 0664); +MODULE_PARM_DESC(frame_detect_flag, "\n frame_detect_flag\n"); + +module_param(frame_detect_fps, uint, 0664); +MODULE_PARM_DESC(frame_detect_fps, "\n frame_detect_fps\n"); + +module_param(frame_detect_receive_count, uint, 0664); +MODULE_PARM_DESC(frame_detect_receive_count, "\n frame_detect_receive_count\n"); + +module_param(frame_detect_drop_count, uint, 0664); +MODULE_PARM_DESC(frame_detect_drop_count, "\n frame_detect_drop_count\n"); + + + + +MODULE_PARM_DESC(bypass_pps, "\n pps_bypass\n"); +module_param(bypass_pps, bool, 0664); + +MODULE_PARM_DESC(platform_type, "\n platform_type\n"); +module_param(platform_type, bool, 0664); + +MODULE_PARM_DESC(process_3d_type, "\n process_3d_type\n"); +module_param(process_3d_type, uint, 0664); + + +MODULE_PARM_DESC(framepacking_support, "\n framepacking_support\n"); +module_param(framepacking_support, uint, 0664); + +MODULE_PARM_DESC(framepacking_width, "\n framepacking_width\n"); +module_param(framepacking_width, uint, 0664); + +MODULE_PARM_DESC(framepacking_height, "\n framepacking_height\n"); +module_param(framepacking_height, uint, 0664); + +MODULE_PARM_DESC(framepacking_blank, "\n framepacking_blank\n"); +module_param(framepacking_blank, uint, 0664); + +MODULE_PARM_DESC(bypass_cm, "\n bypass_cm\n"); +module_param(bypass_cm, bool, 0664); + +#ifdef TV_REVERSE +module_param(reverse, bool, 0644); +MODULE_PARM_DESC(reverse, "reverse /disable reverse"); +#endif + +MODULE_PARM_DESC(toggle_count, "\n toggle count\n"); +module_param(toggle_count, uint, 0664); + +MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n"); +module_param(vpp_hold_line, uint, 0664); + +MODULE_PARM_DESC(stop_update, "\n stop_update\n"); +module_param(stop_update, uint, 0664); + +MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n"); +module_param(reference_zorder, uint, 0664); + +MODULE_DESCRIPTION("AMLOGIC video output driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>"); diff --git a/drivers/amlogic/media/video_sink/video_keeper.c b/drivers/amlogic/media/video_sink/video_keeper.c new file mode 100644 index 0000000..a81460f --- a/dev/null +++ b/drivers/amlogic/media/video_sink/video_keeper.c @@ -0,0 +1,1183 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * drivers/amlogic/media/video_sink/video_keeper.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/err.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/ctype.h> +#include <linux/amlogic/media/frame_sync/ptsserv.h> +#include <linux/amlogic/media/frame_sync/timestamp.h> +#include <linux/amlogic/media/frame_sync/tsync.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/vout/vout_notify.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <linux/clk.h> +/*#include <linux/amlogic/gpio-amlogic.h>*/ +#include <linux/amlogic/media/canvas/canvas.h> +#include <linux/amlogic/media/canvas/canvas_mgr.h> +#include <linux/dma-mapping.h> +#include <linux/dma-contiguous.h> +#ifdef CONFIG_GE2D_KEEP_FRAME +#include <linux/amlogic/media/ge2d/ge2d.h> +#include <linux/amlogic/media/canvas/canvas_mgr.h> +#endif +#include <linux/amlogic/media/codec_mm/codec_mm.h> +#include <linux/amlogic/media/codec_mm/codec_mm_keeper.h> + +#include "video_priv.h" +#include <linux/amlogic/media/video_sink/video_keeper.h> +#include <linux/amlogic/media/registers/register.h> +#include <linux/amlogic/media/video_sink/vpp.h> +#include <linux/amlogic/media/video_sink/video.h> +#include <linux/amlogic/media/utils/vdec_reg.h> + +#define MEM_NAME "video-keeper" +static DEFINE_MUTEX(video_keeper_mutex); + +static unsigned long keep_y_addr, keep_u_addr, keep_v_addr; +static int keep_video_on; +static int keep_video_pip_on; +static int keep_id; +static int keep_head_id; +static int keep_pip_id; +static int keep_pip_head_id; +static int keep_el_id; +static int keep_el_head_id; +static int keep_pip_el_id; +static int keep_pip_el_head_id; + +#define Y_BUFFER_SIZE 0x400000 /* for 1920*1088 */ +#define U_BUFFER_SIZE 0x100000 /* compatible with NV21 */ +#define V_BUFFER_SIZE 0x80000 + +#define RESERVE_CLR_FRAME + +static inline ulong keep_phy_addr(unsigned long addr) +{ + return addr; +} + +#ifdef CONFIG_GE2D_KEEP_FRAME +static int display_canvas_y_dup; +static int display_canvas_u_dup; +static int display_canvas_v_dup; +static struct ge2d_context_s *ge2d_video_context; + +static int ge2d_videotask_init(void) +{ + const char *keep_owner = "keepframe"; + + if (ge2d_video_context == NULL) + ge2d_video_context = create_ge2d_work_queue(); + + if (ge2d_video_context == NULL) { + pr_info("create_ge2d_work_queue video task failed\n"); + return -1; + } + if (!display_canvas_y_dup) + display_canvas_y_dup = canvas_pool_map_alloc_canvas(keep_owner); + if (!display_canvas_u_dup) + display_canvas_u_dup = canvas_pool_map_alloc_canvas(keep_owner); + if (!display_canvas_v_dup) + display_canvas_v_dup = canvas_pool_map_alloc_canvas(keep_owner); + pr_info("create_ge2d_work_queue video task ok\n"); + + return 0; +} + + + +static int ge2d_videotask_release(void) +{ + if (ge2d_video_context) { + destroy_ge2d_work_queue(ge2d_video_context); + ge2d_video_context = NULL; + } + if (display_canvas_y_dup) + canvas_pool_map_free_canvas(display_canvas_y_dup); + if (display_canvas_u_dup) + canvas_pool_map_free_canvas(display_canvas_u_dup); + if (display_canvas_v_dup) + canvas_pool_map_free_canvas(display_canvas_v_dup); + + return 0; +} + +static int ge2d_store_frame_YUV444(u32 cur_index) +{ + u32 y_index, des_index, src_index; + struct canvas_s cs, cd; + ulong yaddr; + u32 ydupindex; + struct config_para_ex_s ge2d_config; + + memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); + + ydupindex = display_canvas_y_dup; + + pr_info("%s cur_index:s:0x%x\n", __func__, cur_index); + /* pr_info("ge2d_store_frame cur_index:d:0x%x\n", canvas_tab[0]); */ + y_index = cur_index & 0xff; + canvas_read(y_index, &cs); + + yaddr = keep_phy_addr(keep_y_addr); + canvas_config(ydupindex, + (ulong) yaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + + canvas_read(ydupindex, &cd); + src_index = y_index; + des_index = ydupindex; + + pr_info("ge2d_canvas_dup ADDR srcy[0x%lx] des[0x%lx]\n", cs.addr, + cd.addr); + + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + + ge2d_config.src_planes[0].addr = cs.addr; + ge2d_config.src_planes[0].w = cs.width; + ge2d_config.src_planes[0].h = cs.height; + + ge2d_config.dst_planes[0].addr = cd.addr; + ge2d_config.dst_planes[0].w = cd.width; + ge2d_config.dst_planes[0].h = cd.height; + + ge2d_config.src_para.canvas_index = src_index; + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.src_para.format = GE2D_FORMAT_M24_YUV444; + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.top = 0; + ge2d_config.src_para.left = 0; + ge2d_config.src_para.width = cs.width; + ge2d_config.src_para.height = cs.height; + ge2d_config.src2_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.canvas_index = des_index; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = GE2D_FORMAT_M24_YUV444; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = cs.width; + ge2d_config.dst_para.height = cs.height; + + if (ge2d_context_config_ex(ge2d_video_context, &ge2d_config) < 0) { + pr_info("ge2d_context_config_ex failed\n"); + return -1; + } + + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); + + return 0; +} + +/* static u32 canvas_tab[1]; */ +static int ge2d_store_frame_NV21(u32 cur_index) +{ + u32 y_index, u_index, des_index, src_index; + struct canvas_s cs0, cs1, cd; + ulong yaddr, uaddr; + u32 ydupindex, udupindex; + struct config_para_ex_s ge2d_config; + + memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); + + ydupindex = display_canvas_y_dup; + udupindex = display_canvas_u_dup; + + pr_info("%s cur_index:s:0x%x\n", __func__, cur_index); + + /* pr_info("ge2d_store_frame cur_index:d:0x%x\n", canvas_tab[0]); */ + yaddr = keep_phy_addr(keep_y_addr); + uaddr = keep_phy_addr(keep_u_addr); + + y_index = cur_index & 0xff; + u_index = (cur_index >> 8) & 0xff; + + canvas_read(y_index, &cs0); + canvas_read(u_index, &cs1); + canvas_config(ydupindex, + (ulong) yaddr, + cs0.width, cs0.height, + CANVAS_ADDR_NOWRAP, cs0.blkmode); + canvas_config(udupindex, + (ulong) uaddr, + cs1.width, cs1.height, + CANVAS_ADDR_NOWRAP, cs1.blkmode); + + canvas_read(ydupindex, &cd); + src_index = ((y_index & 0xff) | ((u_index << 8) & 0x0000ff00)); + des_index = ((ydupindex & 0xff) | ((udupindex << 8) & 0x0000ff00)); + + pr_info("ge2d_store_frame d:0x%x\n", des_index); + + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + + ge2d_config.src_planes[0].addr = cs0.addr; + ge2d_config.src_planes[0].w = cs0.width; + ge2d_config.src_planes[0].h = cs0.height; + ge2d_config.src_planes[1].addr = cs1.addr; + ge2d_config.src_planes[1].w = cs1.width; + ge2d_config.src_planes[1].h = cs1.height; + + ge2d_config.dst_planes[0].addr = cd.addr; + ge2d_config.dst_planes[0].w = cd.width; + ge2d_config.dst_planes[0].h = cd.height; + + ge2d_config.src_para.canvas_index = src_index; + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.src_para.format = GE2D_FORMAT_M24_NV21; + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.top = 0; + ge2d_config.src_para.left = 0; + ge2d_config.src_para.width = cs0.width; + ge2d_config.src_para.height = cs0.height; + ge2d_config.src2_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.canvas_index = des_index; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = GE2D_FORMAT_M24_NV21; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = cs0.width; + ge2d_config.dst_para.height = cs0.height; + + if (ge2d_context_config_ex(ge2d_video_context, &ge2d_config) < 0) { + pr_info("ge2d_context_config_ex failed\n"); + return -1; + } + + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs0.width, cs0.height, + 0, 0, cs0.width, cs0.height); + + return 0; +} + +/* static u32 canvas_tab[1]; */ +static int ge2d_store_frame_YUV420(u32 cur_index) +{ + u32 y_index, u_index, v_index; + struct canvas_s cs, cd; + ulong yaddr, uaddr, vaddr; + u32 ydupindex, udupindex, vdupindex; + struct config_para_ex_s ge2d_config; + + memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); + + ydupindex = display_canvas_y_dup; + udupindex = display_canvas_u_dup; + vdupindex = display_canvas_v_dup; + + pr_info("%s cur_index:s:0x%x\n", __func__, cur_index); + /* operation top line */ + /* Y data */ + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + + y_index = cur_index & 0xff; + canvas_read(y_index, &cs); + ge2d_config.src_planes[0].addr = cs.addr; + ge2d_config.src_planes[0].w = cs.width; + ge2d_config.src_planes[0].h = cs.height; + ge2d_config.src_planes[1].addr = 0; + ge2d_config.src_planes[1].w = 0; + ge2d_config.src_planes[1].h = 0; + ge2d_config.src_planes[2].addr = 0; + ge2d_config.src_planes[2].w = 0; + ge2d_config.src_planes[2].h = 0; + + yaddr = keep_phy_addr(keep_y_addr); + canvas_config(ydupindex, + (ulong) yaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + + canvas_read(ydupindex, &cd); + ge2d_config.dst_planes[0].addr = cd.addr; + ge2d_config.dst_planes[0].w = cd.width; + ge2d_config.dst_planes[0].h = cd.height; + ge2d_config.dst_planes[1].addr = 0; + ge2d_config.dst_planes[1].w = 0; + ge2d_config.dst_planes[1].h = 0; + ge2d_config.dst_planes[2].addr = 0; + ge2d_config.dst_planes[2].w = 0; + ge2d_config.dst_planes[2].h = 0; + + ge2d_config.src_key.key_enable = 0; + ge2d_config.src_key.key_mask = 0; + ge2d_config.src_key.key_mode = 0; + ge2d_config.src_key.key_color = 0; + + ge2d_config.src_para.canvas_index = y_index; + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.src_para.format = GE2D_FMT_S8_Y; + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.x_rev = 0; + ge2d_config.src_para.y_rev = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.top = 0; + ge2d_config.src_para.left = 0; + ge2d_config.src_para.width = cs.width; + ge2d_config.src_para.height = cs.height; + ge2d_config.src2_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.canvas_index = ydupindex; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = GE2D_FMT_S8_Y; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.x_rev = 0; + ge2d_config.dst_para.y_rev = 0; + ge2d_config.dst_xy_swap = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = cs.width; + ge2d_config.dst_para.height = cs.height; + + if (ge2d_context_config_ex(ge2d_video_context, &ge2d_config) < 0) { + pr_info("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); + + /* U data */ + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + + u_index = (cur_index >> 8) & 0xff; + canvas_read(u_index, &cs); + ge2d_config.src_planes[0].addr = cs.addr; + ge2d_config.src_planes[0].w = cs.width; + ge2d_config.src_planes[0].h = cs.height; + ge2d_config.src_planes[1].addr = 0; + ge2d_config.src_planes[1].w = 0; + ge2d_config.src_planes[1].h = 0; + ge2d_config.src_planes[2].addr = 0; + ge2d_config.src_planes[2].w = 0; + ge2d_config.src_planes[2].h = 0; + + uaddr = keep_phy_addr(keep_u_addr); + canvas_config(udupindex, + (ulong) uaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + + canvas_read(udupindex, &cd); + ge2d_config.dst_planes[0].addr = cd.addr; + ge2d_config.dst_planes[0].w = cd.width; + ge2d_config.dst_planes[0].h = cd.height; + ge2d_config.dst_planes[1].addr = 0; + ge2d_config.dst_planes[1].w = 0; + ge2d_config.dst_planes[1].h = 0; + ge2d_config.dst_planes[2].addr = 0; + ge2d_config.dst_planes[2].w = 0; + ge2d_config.dst_planes[2].h = 0; + + ge2d_config.src_key.key_enable = 0; + ge2d_config.src_key.key_mask = 0; + ge2d_config.src_key.key_mode = 0; + ge2d_config.src_key.key_color = 0; + + ge2d_config.src_para.canvas_index = u_index; + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.src_para.format = GE2D_FMT_S8_CB; + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.x_rev = 0; + ge2d_config.src_para.y_rev = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.top = 0; + ge2d_config.src_para.left = 0; + ge2d_config.src_para.width = cs.width; + ge2d_config.src_para.height = cs.height; + + ge2d_config.dst_para.canvas_index = udupindex; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = GE2D_FMT_S8_CB; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.x_rev = 0; + ge2d_config.dst_para.y_rev = 0; + ge2d_config.dst_xy_swap = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = cs.width; + ge2d_config.dst_para.height = cs.height; + + if (ge2d_context_config_ex(ge2d_video_context, &ge2d_config) < 0) { + pr_info("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); + + /* operation top line */ + /* V data */ + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + + v_index = (cur_index >> 16) & 0xff; + canvas_read(v_index, &cs); + ge2d_config.src_planes[0].addr = cs.addr; + ge2d_config.src_planes[0].w = cs.width; + ge2d_config.src_planes[0].h = cs.height; + ge2d_config.src_planes[1].addr = 0; + ge2d_config.src_planes[1].w = 0; + ge2d_config.src_planes[1].h = 0; + ge2d_config.src_planes[2].addr = 0; + ge2d_config.src_planes[2].w = 0; + ge2d_config.src_planes[2].h = 0; + + vaddr = keep_phy_addr(keep_v_addr); + canvas_config(vdupindex, + (ulong) vaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + + ge2d_config.dst_planes[0].addr = cd.addr; + ge2d_config.dst_planes[0].w = cd.width; + ge2d_config.dst_planes[0].h = cd.height; + ge2d_config.dst_planes[1].addr = 0; + ge2d_config.dst_planes[1].w = 0; + ge2d_config.dst_planes[1].h = 0; + ge2d_config.dst_planes[2].addr = 0; + ge2d_config.dst_planes[2].w = 0; + ge2d_config.dst_planes[2].h = 0; + + ge2d_config.src_key.key_enable = 0; + ge2d_config.src_key.key_mask = 0; + ge2d_config.src_key.key_mode = 0; + ge2d_config.src_key.key_color = 0; + + ge2d_config.src_para.canvas_index = v_index; + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.src_para.format = GE2D_FMT_S8_CR; + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.x_rev = 0; + ge2d_config.src_para.y_rev = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.top = 0; + ge2d_config.src_para.left = 0; + ge2d_config.src_para.width = cs.width; + ge2d_config.src_para.height = cs.height; + + ge2d_config.dst_para.canvas_index = vdupindex; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = GE2D_FMT_S8_CR; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.x_rev = 0; + ge2d_config.dst_para.y_rev = 0; + ge2d_config.dst_xy_swap = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = cs.width; + ge2d_config.dst_para.height = cs.height; + + if (ge2d_context_config_ex(ge2d_video_context, &ge2d_config) < 0) { + pr_info("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); + return 0; +} + +static void ge2d_keeplastframe_block(int cur_index, int format) +{ + u32 y_index, u_index, v_index; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + u32 y_index2, u_index2, v_index2; +#endif + + video_module_lock(); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + y_index = disp_canvas_index[0][0]; + y_index2 = disp_canvas_index[1][0]; + u_index = disp_canvas_index[0][1]; + u_index2 = disp_canvas_index[1][1]; + v_index = disp_canvas_index[0][2]; + v_index2 = disp_canvas_index[1][2]; +#else + /* + *cur_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + + * get_video_cur_dev->viu_off); + */ + y_index = cur_index & 0xff; + u_index = (cur_index >> 8) & 0xff; + v_index = (cur_index >> 16) & 0xff; +#endif + + switch (format) { + case GE2D_FORMAT_M24_YUV444: + ge2d_store_frame_YUV444(cur_index); + canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + canvas_update_addr(y_index2, keep_phy_addr(keep_y_addr)); +#endif + break; + case GE2D_FORMAT_M24_NV21: + ge2d_store_frame_NV21(cur_index); + canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); + canvas_update_addr(u_index, keep_phy_addr(keep_u_addr)); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + canvas_update_addr(y_index2, keep_phy_addr(keep_y_addr)); + canvas_update_addr(u_index2, keep_phy_addr(keep_u_addr)); +#endif + break; + case GE2D_FORMAT_M24_YUV420: + ge2d_store_frame_YUV420(cur_index); + canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); + canvas_update_addr(u_index, keep_phy_addr(keep_u_addr)); + canvas_update_addr(v_index, keep_phy_addr(keep_v_addr)); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + canvas_update_addr(y_index2, keep_phy_addr(keep_y_addr)); + canvas_update_addr(u_index2, keep_phy_addr(keep_u_addr)); + canvas_update_addr(v_index2, keep_phy_addr(keep_v_addr)); +#endif + break; + default: + break; + } + video_module_unlock(); + +} +#endif + +#define FETCHBUF_SIZE (64*1024) /*DEBUG_TMP*/ +static int canvas_dup(ulong dst, ulong src_paddr, ulong size) +{ + void *src_addr = codec_mm_phys_to_virt(src_paddr); + void *dst_addr = codec_mm_phys_to_virt(dst); + + if (src_paddr && dst && src_addr && dst_addr) { + dma_addr_t dma_addr = 0; + + memcpy(dst_addr, src_addr, size); + dma_addr = dma_map_single(get_video_device(), dst_addr, + size, DMA_TO_DEVICE); + dma_unmap_single(get_video_device(), dma_addr, + FETCHBUF_SIZE, DMA_TO_DEVICE); + return 1; + } + + return 0; +} + +#ifdef RESERVE_CLR_FRAME +static int free_alloced_keep_buffer(void) +{ + if (keep_y_addr) { + codec_mm_free_for_dma(MEM_NAME, keep_y_addr); + keep_y_addr = 0; + } + + if (keep_u_addr) { + codec_mm_free_for_dma(MEM_NAME, keep_u_addr); + keep_u_addr = 0; + } + + if (keep_v_addr) { + codec_mm_free_for_dma(MEM_NAME, keep_v_addr); + keep_v_addr = 0; + } + return 0; +} + +static int alloc_keep_buffer(void) +{ + int flags = CODEC_MM_FLAGS_DMA | + CODEC_MM_FLAGS_FOR_VDECODER; +#ifndef CONFIG_GE2D_KEEP_FRAME + /* + * if not used ge2d. + * need CPU access. + */ + flags = CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_FOR_VDECODER; +#endif + if ((flags & CODEC_MM_FLAGS_FOR_VDECODER) && + codec_mm_video_tvp_enabled()) + /*TVP TODO for MULTI*/ + flags |= CODEC_MM_FLAGS_TVP; + + if (!keep_y_addr) { + keep_y_addr = codec_mm_alloc_for_dma( + MEM_NAME, + PAGE_ALIGN(Y_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + if (!keep_y_addr) { + pr_err("%s: failed to alloc y addr\n", __func__); + goto err1; + } + } + + if (!keep_u_addr) { + keep_u_addr = codec_mm_alloc_for_dma( + MEM_NAME, + PAGE_ALIGN(U_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + if (!keep_u_addr) { + pr_err("%s: failed to alloc u addr\n", __func__); + goto err1; + } + } + + if (!keep_v_addr) { + keep_v_addr = codec_mm_alloc_for_dma( + MEM_NAME, + PAGE_ALIGN(V_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + if (!keep_v_addr) { + pr_err("%s: failed to alloc v addr\n", __func__); + goto err1; + } + } + pr_info("alloced keep buffer yaddr=%p,u_addr=%p,v_addr=%p,tvp=%d\n", + (void *)keep_y_addr, + (void *)keep_u_addr, + (void *)keep_v_addr, + codec_mm_video_tvp_enabled()); + return 0; + + err1: + free_alloced_keep_buffer(); + return -ENOMEM; +} + +/* + *flags,used per bit: + *deflaut free alloced keeper buffer. + *0x1: free scatters keeper.. + *0x2: + */ +void try_free_keep_video(int flags) +{ + int free_scatter_keeper = flags & 0x1; + + if (keep_video_on || free_scatter_keeper) { + /*pr_info("disabled keep video before free keep buffer.\n");*/ + keep_video_on = 0; + if (!get_video_enabled()) { + /*if not disable video,changed to 2 for */ + pr_info("disiabled video for next before free keep buffer!\n"); + _video_set_disable(VIDEO_DISABLE_FORNEXT); + } else if (get_video_enabled()) { + safe_disable_videolayer(); + } + } + mutex_lock(&video_keeper_mutex); + video_keeper_new_frame_notify(); + free_alloced_keep_buffer(); + mutex_unlock(&video_keeper_mutex); +} +EXPORT_SYMBOL(try_free_keep_video); +#endif + +void try_free_keep_videopip(int flags) +{ + int free_scatter_keeper = flags & 0x1; + + if (keep_video_pip_on || free_scatter_keeper) { + /*pr_info("disiabled keep video before free keep buffer.\n");*/ + keep_video_pip_on = 0; + if (!get_videopip_enabled()) { + /*if not disable video,changed to 2 for */ + pr_info("disabled videopip for next before free keep buffer!\n"); + _videopip_set_disable(VIDEO_DISABLE_FORNEXT); + } else if (get_videopip_enabled()) { + safe_disable_videolayer2(); + } + } + mutex_lock(&video_keeper_mutex); + video_pip_keeper_new_frame_notify(); + free_alloced_keep_buffer(); + mutex_unlock(&video_keeper_mutex); +} +EXPORT_SYMBOL(try_free_keep_videopip); + +static void video_keeper_update_keeper_mem( + void *mem_handle, int type, + int *id) +{ + int ret; + int old_id = *id; + + if (!mem_handle) + return; + ret = codec_mm_keeper_mask_keep_mem(mem_handle, + type); + if (ret > 0) { + if (old_id > 0 && ret != old_id) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(old_id, 120); + } + *id = ret; + } +} + +static int video_keeper_frame_keep_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + int type = MEM_TYPE_CODEC_MM; + + if (cur_dispbuf->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + video_keeper_update_keeper_mem( + cur_dispbuf->mem_handle, + type, + &keep_id); + video_keeper_update_keeper_mem( + cur_dispbuf->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_head_id); + if (cur_dispbuf_el) { + if (cur_dispbuf->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + else + type = MEM_TYPE_CODEC_MM; + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_handle, + type, + &keep_el_id); + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_el_head_id); + } + return (keep_id + keep_head_id) > 0; +} + +static int video_pip_keeper_frame_keep_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + int type = MEM_TYPE_CODEC_MM; + + if (cur_dispbuf) { + if (cur_dispbuf->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + video_keeper_update_keeper_mem( + cur_dispbuf->mem_handle, + type, + &keep_pip_id); + video_keeper_update_keeper_mem( + cur_dispbuf->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_head_id); + } + if (cur_dispbuf_el) { + if (cur_dispbuf_el->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + else + type = MEM_TYPE_CODEC_MM; + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_handle, + type, + &keep_pip_el_id); + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_el_head_id); + } + return (keep_pip_id + keep_pip_head_id) > 0; +} + +/* + * call in irq. + *don't used mutex + */ +void video_keeper_new_frame_notify(void) +{ + if (keep_video_on) { + pr_info("new frame show, free keeper\n"); + keep_video_on = 0; + } + if (keep_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_id, 120); + keep_id = -1; + } + if (keep_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_head_id, 120); + keep_head_id = -1; + } + + if (keep_el_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_el_id, 120); + keep_el_id = -1; + } + if (keep_el_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_el_head_id, 120); + keep_el_head_id = -1; + } +} + +void video_pip_keeper_new_frame_notify(void) +{ + if (keep_video_pip_on) { + pr_info("new frame show, pip free keeper\n"); + keep_video_pip_on = 0; + } + if (keep_pip_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_id, 120); + keep_pip_id = -1; + } + if (keep_pip_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_head_id, 120); + keep_pip_head_id = -1; + } + if (keep_pip_el_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_id, 120); + keep_pip_el_id = -1; + } + if (keep_pip_el_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_head_id, 120); + keep_pip_el_head_id = -1; + } + +} + + +static unsigned int vf_keep_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + u32 cur_index; + u32 y_index, u_index, v_index; + struct canvas_s cs0, cs1, cs2, cd; + int ret; + + if (!cur_dispbuf) { + pr_info("keep exit without cur_dispbuf\n"); + return 0; + } + + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + pr_info("keep exit is skip current\n"); + return 0; + } + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE + ext_frame_capture_poll(1); /*pull if have capture end frame */ +#endif + + if (get_blackout_policy()) { + pr_info("keep exit is skip current\n"); + return 0; + } + + if (VSYNC_RD_MPEG_REG(DI_IF1_GEN_REG) & 0x1) { + pr_info("keep exit is di\n"); + return 0; + } + + ret = video_keeper_frame_keep_locked( + cur_dispbuf, + cur_dispbuf_el); + if (ret) { + /*keeped ok with codec keeper!*/ + keep_video_on = 1; + return 1; + } +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + if (codec_mm_video_tvp_enabled()) { + pr_info("keep exit is TVP\n"); + return 0; + } +#endif + + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + /* todo: duplicate compressed video frame */ + pr_info("keep exit is skip VIDTYPE_COMPRESS\n"); + return -1; + } + cur_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + + get_video_cur_dev()->viu_off); + y_index = cur_index & 0xff; + u_index = (cur_index >> 8) & 0xff; + v_index = (cur_index >> 16) & 0xff; + canvas_read(y_index, &cd); + + if ((cd.width * cd.height) <= 2048 * 1088 + && !keep_y_addr) { + alloc_keep_buffer(); + } + if (!keep_y_addr + || (cur_dispbuf->type & VIDTYPE_VIU_422) + == VIDTYPE_VIU_422) { + /* no support VIDTYPE_VIU_422... */ + pr_info("%s:no support VIDTYPE_VIU_422\n", __func__); + return -1; + } + + if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) { + pr_info("%s keep_y_addr=%p %x\n", + __func__, (void *)keep_y_addr, + canvas_get_addr(y_index)); + } + + if ((cur_dispbuf->type & VIDTYPE_VIU_422) == VIDTYPE_VIU_422) { + return -1; + } else if ((cur_dispbuf->type & VIDTYPE_VIU_444) == VIDTYPE_VIU_444) { + if ((Y_BUFFER_SIZE < (cd.width * cd.height))) { + pr_info + ("[%s::%d] error:data>buf size: %x,%x,%x, %x,%x\n", + __func__, __LINE__, Y_BUFFER_SIZE, + U_BUFFER_SIZE, V_BUFFER_SIZE, + cd.width, cd.height); + return -1; + } +#ifdef CONFIG_GE2D_KEEP_FRAME + ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_YUV444); +#else + if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cd.width) * (cd.height))) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + canvas_update_addr(disp_canvas_index[0][0], + keep_phy_addr(keep_y_addr)); + canvas_update_addr(disp_canvas_index[1][0], + keep_phy_addr(keep_y_addr)); +#else + canvas_update_addr(y_index, + keep_phy_addr(keep_y_addr)); +#endif + } +#endif + if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) + pr_info("%s: VIDTYPE_VIU_444\n", __func__); + } else if ((cur_dispbuf->type & VIDTYPE_VIU_NV21) == VIDTYPE_VIU_NV21) { + canvas_read(y_index, &cs0); + canvas_read(u_index, &cs1); + if ((Y_BUFFER_SIZE < (cs0.width * cs0.height)) + || (U_BUFFER_SIZE < (cs1.width * cs1.height))) { + pr_info("## [%s::%d] error: yuv data size larger", + __func__, __LINE__); + return -1; + } +#ifdef CONFIG_GE2D_KEEP_FRAME + ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_NV21); +#else + if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cs0.width * cs0.height)) + && canvas_dup(keep_phy_addr(keep_u_addr), + canvas_get_addr(u_index), + (cs1.width * cs1.height))) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + canvas_update_addr(disp_canvas_index[0][0], + keep_phy_addr(keep_y_addr)); + canvas_update_addr(disp_canvas_index[1][0], + keep_phy_addr(keep_y_addr)); + canvas_update_addr(disp_canvas_index[0][1], + keep_phy_addr(keep_u_addr)); + canvas_update_addr(disp_canvas_index[1][1], + keep_phy_addr(keep_u_addr)); +#else + canvas_update_addr(y_index, + keep_phy_addr(keep_y_addr)); + canvas_update_addr(u_index, + keep_phy_addr(keep_u_addr)); +#endif + } +#endif + if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) + pr_info("%s: VIDTYPE_VIU_NV21\n", __func__); + } else { + canvas_read(y_index, &cs0); + canvas_read(u_index, &cs1); + canvas_read(v_index, &cs2); + + if ((Y_BUFFER_SIZE < (cs0.width * cs0.height)) + || (U_BUFFER_SIZE < (cs1.width * cs1.height)) + || (V_BUFFER_SIZE < (cs2.width * cs2.height))) { + pr_info("## [%s::%d] error: yuv data size larger than buf size: %x,%x,%x, %x,%x, %x,%x, %x,%x,\n", + __func__, __LINE__, Y_BUFFER_SIZE, + U_BUFFER_SIZE, V_BUFFER_SIZE, cs0.width, + cs0.height, cs1.width, cs1.height, cs2.width, + cs2.height); + return -1; + } +#ifdef CONFIG_GE2D_KEEP_FRAME + ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_YUV420); +#else + if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && + /*must not the same address */ + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cs0.width * cs0.height)) + && canvas_dup(keep_phy_addr(keep_u_addr), + canvas_get_addr(u_index), + (cs1.width * cs1.height)) + && canvas_dup(keep_phy_addr(keep_v_addr), + canvas_get_addr(v_index), + (cs2.width * cs2.height))) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + canvas_update_addr(disp_canvas_index[0][0], + keep_phy_addr(keep_y_addr)); + canvas_update_addr(disp_canvas_index[1][0], + keep_phy_addr(keep_y_addr)); + canvas_update_addr(disp_canvas_index[0][1], + keep_phy_addr(keep_u_addr)); + canvas_update_addr(disp_canvas_index[1][1], + keep_phy_addr(keep_u_addr)); + canvas_update_addr(disp_canvas_index[0][2], + keep_phy_addr(keep_v_addr)); + canvas_update_addr(disp_canvas_index[1][2], + keep_phy_addr(keep_v_addr)); +#else + canvas_update_addr(y_index, + keep_phy_addr(keep_y_addr)); + canvas_update_addr(u_index, + keep_phy_addr(keep_u_addr)); + canvas_update_addr(v_index, + keep_phy_addr(keep_v_addr)); +#endif + } + + if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) + pr_info("%s: VIDTYPE_VIU_420\n", __func__); +#endif + } + keep_video_on = 1; + pr_info("%s: keep video on with keep\n", __func__); + return 1; + +} + +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + //u32 cur_index; + //u32 y_index, u_index, v_index; + //struct canvas_s cs0, cs1, cs2, cd; + int ret; + + if (!cur_dispbuf) { + pr_info("keep pip exit without cur_dispbuf\n"); + return 0; + } + + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + pr_info("flag: keep pip exit is skip current\n"); + return 0; + } + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE + ext_frame_capture_poll(1); /*pull if have capture end frame */ +#endif + + if (get_blackout_pip_policy()) { + pr_info("policy: keep exit is skip current\n"); + return 0; + } + + ret = video_pip_keeper_frame_keep_locked( + cur_dispbuf, + cur_dispbuf_el); + + if (ret) { + /*keeped ok with codec keeper!*/ + pr_info("keep pip buffer on!\n"); + keep_video_pip_on = 1; + return 1; + } + + keep_video_pip_on = 0; + return 0; +} + +unsigned int vf_keep_current( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf2) +{ + unsigned int ret; + + mutex_lock(&video_keeper_mutex); + ret = vf_keep_current_locked( + cur_dispbuf, cur_dispbuf2); + mutex_unlock(&video_keeper_mutex); + return ret; +} + +int __init video_keeper_init(void) +{ +#ifdef CONFIG_GE2D_KEEP_FRAME + /* video_frame_getmem(); */ + ge2d_videotask_init(); +#endif + return 0; +} +void __exit video_keeper_exit(void) +{ +#ifdef CONFIG_GE2D_KEEP_FRAME + ge2d_videotask_release(); +#endif +} + diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h new file mode 100644 index 0000000..9af8847 --- a/dev/null +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * drivers/amlogic/media/video_sink/video_priv.h + * + * 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. + * + */ + +#ifndef VIDEO_PRIV_HEADER_HH +#define VIDEO_PRIV_HEADER_HH + +#include <linux/amlogic/media/video_sink/vpp.h> + +#define DEBUG_FLAG_BLACKOUT 0x1 +#define DEBUG_FLAG_PRINT_TOGGLE_FRAME 0x2 +#define DEBUG_FLAG_PRINT_RDMA 0x4 +#define DEBUG_FLAG_LOG_RDMA_LINE_MAX 0x100 +#define DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT 0x10000 +#define DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC 0x20000 +#define DEBUG_FLAG_RDMA_WAIT_1 0x40000 +#define DEBUG_FLAG_VSYNC_DONONE 0x80000 +#define DEBUG_FLAG_GOFIELD_MANUL 0x100000 +#define DEBUG_FLAG_LATENCY 0x200000 +#define DEBUG_FLAG_PTS_TRACE 0x400000 +#define DEBUG_FLAG_FRAME_DETECT 0x800000 + +/*for video.c's static int debug_flag;*/ + +#define VOUT_TYPE_TOP_FIELD 0 +#define VOUT_TYPE_BOT_FIELD 1 +#define VOUT_TYPE_PROG 2 + +#define VIDEO_DISABLE_NONE 0 +#define VIDEO_DISABLE_NORMAL 1 +#define VIDEO_DISABLE_FORNEXT 2 + +#define VIDEO_NOTIFY_TRICK_WAIT 0x01 +#define VIDEO_NOTIFY_PROVIDER_GET 0x02 +#define VIDEO_NOTIFY_PROVIDER_PUT 0x04 +#define VIDEO_NOTIFY_FRAME_WAIT 0x08 +#define VIDEO_NOTIFY_POS_CHANGED 0x10 +#define VIDEO_NOTIFY_NEED_NO_COMP 0x20 + +struct video_dev_s { + int vpp_off; + int viu_off; +}; + +struct mif_pos_s { + u32 id; + u32 vd_reg_offt; + u32 afbc_reg_offt; + + /* frame original size */ + u32 src_w; + u32 src_h; + + /* mif start - end lines */ + u32 start_x_lines; + u32 end_x_lines; + u32 start_y_lines; + u32 end_y_lines; + + /* left and right eye position, skip flag. */ + /* And if non 3d case, left eye = right eye */ + u32 l_hs_luma; + u32 l_he_luma; + u32 l_hs_chrm; + u32 l_he_chrm; + u32 r_hs_luma; + u32 r_he_luma; + u32 r_hs_chrm; + u32 r_he_chrm; + u32 h_skip; + u32 l_vs_luma; + u32 l_ve_luma; + u32 l_vs_chrm; + u32 l_ve_chrm; + u32 r_vs_luma; + u32 r_ve_luma; + u32 r_vs_chrm; + u32 r_ve_chrm; + u32 v_skip; + + bool reverse; + + bool skip_afbc; +}; + +struct scaler_setting_s { + u32 id; + u32 misc_reg_offt; + + bool sc_h_enable; + bool sc_v_enable; + bool sc_top_enable; + + u32 vinfo_width; + u32 vinfo_height; + /* u32 VPP_pic_in_height_; */ + /* u32 VPP_line_in_length_; */ + + struct vpp_frame_par_s *frame_par; +}; + +struct blend_setting_s { + u32 id; + u32 misc_reg_offt; + + u32 layer_alpha; + + u32 preblend_h_start; + u32 preblend_h_end; + u32 preblend_v_start; + u32 preblend_v_end; + + u32 preblend_h_size; + + u32 postblend_h_start; + u32 postblend_h_end; + u32 postblend_v_start; + u32 postblend_v_end; + + u32 postblend_h_size; + + struct vpp_frame_par_s *frame_par; +}; + +void safe_disable_videolayer(void); +void safe_disable_videolayer2(void); +void update_cur_dispbuf(void *buf); + +/*for video related files only.*/ +void video_module_lock(void); +void video_module_unlock(void); +struct video_dev_s *get_video_cur_dev(void); +struct vframe_s *get_cur_dispbuf(void); + +int get_video_debug_flags(void); +int _video_set_disable(u32 val); +int _videopip_set_disable(u32 val); +u32 get_video_enabled(void); +u32 get_videopip_enabled(void); +struct device *get_video_device(void); + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE +int ext_frame_capture_poll(int endflags); +#endif + +extern u32 disp_canvas_index[2][6]; +#endif +/*VIDEO_PRIV_HEADER_HH*/ diff --git a/drivers/amlogic/media/video_sink/videolog.h b/drivers/amlogic/media/video_sink/videolog.h new file mode 100644 index 0000000..6f37b38a --- a/dev/null +++ b/drivers/amlogic/media/video_sink/videolog.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * drivers/amlogic/media/video_sink/videolog.h + * + * 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. + * + */ + +#define LOG_LEVEL_VAR amlog_level_video +#define LOG_MASK_VAR amlog_mask_video + +#define LOG_LEVEL_ERROR 0 +#define LOG_MASK_TIMESTAMP 0x00000001UL +#define LOG_MASK_FRAMEINFO 0x00000002UL +#define LOG_MASK_FRAMESKIP 0x00000004UL +#define LOG_MASK_SLOWSYNC 0x00000008UL +#define LOG_MASK_KEEPBUF 0x00000010UL +#define LOG_MASK_SYSFS 0x00000020UL +#define LOG_MASK_VINFO 0x00000040UL +#define LOG_MASK_MODULE 0x00000080UL +#define LOG_MASK_VPP 0x00000100UL + +#define LOG_MASK_DESC \ +"[0x01]:TIMESTAMP,[0x02]:FRAMEINFO,[0x04]:FRAMESKIP,[0x08]:SLOWSYNC,[0x10]:KEEPBUF,[0x20]:SYSFS,[0x40]:VINFO,[0x80]:MODULE." diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c new file mode 100644 index 0000000..162acab --- a/dev/null +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -0,0 +1,3216 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * drivers/amlogic/media/video_sink/vpp.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/kernel.h> +#include <linux/err.h> +#include <linux/amlogic/media/vout/vinfo.h> +#include <linux/amlogic/media/utils/amports_config.h> +#include <linux/amlogic/media/vpu/vpu.h> +#include <linux/amlogic/media/vfm/vframe.h> +#include <linux/amlogic/media/video_sink/video.h> +#include <linux/amlogic/media/video_sink/vpp.h> + +#include "videolog.h" +/* #define CONFIG_VIDEO_LOG */ +#ifdef CONFIG_VIDEO_LOG +#define AMLOG +#endif +#include <linux/amlogic/media/utils/amlog.h> +#include <linux/amlogic/media/registers/register.h> +#include <linux/amlogic/media/utils/vdec_reg.h> + +#include "video_priv.h" + +#define MAX_NONLINEAR_FACTOR 0x40 + +/* vpp filter coefficients */ +#define COEF_BICUBIC 0 +#define COEF_3POINT_TRIANGLE 1 +#define COEF_4POINT_TRIANGLE 2 +#define COEF_BILINEAR 3 +#define COEF_2POINT_BILINEAR 4 +#define COEF_BICUBIC_SHARP 5 +#define COEF_3POINT_TRIANGLE_SHARP 6 +#define COEF_3POINT_BSPLINE 7 +#define COEF_4POINT_BSPLINE 8 +#define COEF_3D_FILTER 9 +#define COEF_NULL 0xff +#define TOTAL_FILTERS 10 + +#define VPP_SPEED_FACTOR 0x110ULL +#define SUPER_SCALER_V_FACTOR 100 +#define PPS_FRAC_BITS 24 +#define PPS_INT_BITS 4 + +struct filter_info_s { + u32 cur_vert_filter; + u32 cur_horz_filter; + u32 last_vert_filter; + u32 last_horz_filter; + u32 scaler_filter_cnt; +}; + +static struct filter_info_s gfilter[MAX_VD_LAYERS]; + +const u32 vpp_filter_coefs_bicubic_sharp[] = { + 3, + 33 | 0x8000, + /* 0x01f80090, 0x01f80100, 0xff7f0200, 0xfe7f0300, */ + 0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300, + 0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900, + 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff, + 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, + 0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd, + 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb, + 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, + 0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9, + 0xf84848f8 +}; + +const u32 vpp_filter_coefs_bicubic[] = { + 4, + 33, + 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, + 0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900, + 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff, + 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, + 0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd, + 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb, + 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, + 0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9, + 0xf84848f8 +}; + +const u32 vpp_filter_coefs_bilinear[] = { + 4, + 33, + 0x00800000, 0x007e0200, 0x007c0400, 0x007a0600, + 0x00780800, 0x00760a00, 0x00740c00, 0x00720e00, + 0x00701000, 0x006e1200, 0x006c1400, 0x006a1600, + 0x00681800, 0x00661a00, 0x00641c00, 0x00621e00, + 0x00602000, 0x005e2200, 0x005c2400, 0x005a2600, + 0x00582800, 0x00562a00, 0x00542c00, 0x00522e00, + 0x00503000, 0x004e3200, 0x004c3400, 0x004a3600, + 0x00483800, 0x00463a00, 0x00443c00, 0x00423e00, + 0x00404000 +}; + +const u32 vpp_3d_filter_coefs_bilinear[] = { + 2, + 33, + 0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, + 0x78080000, 0x760a0000, 0x740c0000, 0x720e0000, + 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000, + 0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, + 0x60200000, 0x5e220000, 0x5c240000, 0x5a260000, + 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000, + 0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, + 0x48380000, 0x463a0000, 0x443c0000, 0x423e0000, + 0x40400000 +}; + +const u32 vpp_filter_coefs_3point_triangle[] = { + 3, + 33, + 0x40400000, 0x3f400100, 0x3d410200, 0x3c410300, + 0x3a420400, 0x39420500, 0x37430600, 0x36430700, + 0x35430800, 0x33450800, 0x32450900, 0x31450a00, + 0x30450b00, 0x2e460c00, 0x2d460d00, 0x2c470d00, + 0x2b470e00, 0x29480f00, 0x28481000, 0x27481100, + 0x26491100, 0x25491200, 0x24491300, 0x234a1300, + 0x224a1400, 0x214a1500, 0x204a1600, 0x1f4b1600, + 0x1e4b1700, 0x1d4b1800, 0x1c4c1800, 0x1b4c1900, + 0x1a4c1a00 +}; + +/* point_num =4, filt_len =4, group_num = 64, [1 2 1] */ +const u32 vpp_filter_coefs_4point_triangle[] = { + 4, + 33, + 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, + 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, + 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, + 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, + 0x18382808, 0x18382808, 0x17372909, 0x17372909, + 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, + 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, + 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, + 0x10303010 +}; +/* + *4th order (cubic) b-spline + *filt_cubic point_num =4, filt_len =4, group_num = 64, [1 5 1] + */ +const u32 vpp_filter_coefs_4point_bspline[] = { + 4, + 33, + 0x15561500, 0x14561600, 0x13561700, 0x12561800, + 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00, + 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200, + 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700, + 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01, + 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201, + 0x05473301, 0x05463401, 0x04453601, 0x04433702, + 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02, + 0x033d3d03 +}; +/*3rd order (quadratic) b-spline*/ +/*filt_quadratic, point_num =3, filt_len =3, group_num = 64, [1 6 1] */ +const u32 vpp_filter_coefs_3point_bspline[] = { + 3, + 33, + 0x40400000, 0x3e420000, 0x3c440000, 0x3a460000, + 0x38480000, 0x364a0000, 0x344b0100, 0x334c0100, + 0x314e0100, 0x304f0100, 0x2e500200, 0x2c520200, + 0x2a540200, 0x29540300, 0x27560300, 0x26570300, + 0x24580400, 0x23590400, 0x215a0500, 0x205b0500, + 0x1e5c0600, 0x1d5c0700, 0x1c5d0700, 0x1a5e0800, + 0x195e0900, 0x185e0a00, 0x175f0a00, 0x15600b00, + 0x14600c00, 0x13600d00, 0x12600e00, 0x11600f00, + 0x10601000 +}; +/*filt_triangle, point_num =3, filt_len =2.6, group_num = 64, [1 7 1] */ +const u32 vpp_filter_coefs_3point_triangle_sharp[] = { + 3, + 33, + 0x40400000, 0x3e420000, 0x3d430000, 0x3b450000, + 0x3a460000, 0x38480000, 0x37490000, 0x354b0000, + 0x344c0000, 0x324e0000, 0x314f0000, 0x2f510000, + 0x2e520000, 0x2c540000, 0x2b550000, 0x29570000, + 0x28580000, 0x265a0000, 0x245c0000, 0x235d0000, + 0x215f0000, 0x20600000, 0x1e620000, 0x1d620100, + 0x1b620300, 0x19630400, 0x17630600, 0x15640700, + 0x14640800, 0x12640a00, 0x11640b00, 0x0f650c00, + 0x0d660d00 +}; + +const u32 vpp_filter_coefs_2point_binilear[] = { + 2, + 33, + 0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, + 0x78080000, 0x760a0000, 0x740c0000, 0x720e0000, + 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000, + 0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, + 0x60200000, 0x5e220000, 0x5c240000, 0x5a260000, + 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000, + 0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, + 0x48380000, 0x463a0000, 0x443c0000, 0x423e0000, + 0x40400000 +}; + +static const u32 *filter_table[] = { + vpp_filter_coefs_bicubic, + vpp_filter_coefs_3point_triangle, + vpp_filter_coefs_4point_triangle, + vpp_filter_coefs_bilinear, + vpp_filter_coefs_2point_binilear, + vpp_filter_coefs_bicubic_sharp, + vpp_filter_coefs_3point_triangle_sharp, + vpp_filter_coefs_3point_bspline, + vpp_filter_coefs_4point_bspline, + vpp_3d_filter_coefs_bilinear +}; + +static int chroma_filter_table[] = { + COEF_BICUBIC, /* bicubic */ + COEF_3POINT_TRIANGLE, + COEF_4POINT_TRIANGLE, + COEF_4POINT_TRIANGLE, /* bilinear */ + COEF_2POINT_BILINEAR, + COEF_3POINT_TRIANGLE, /* bicubic_sharp */ + COEF_3POINT_TRIANGLE, /* 3point_triangle_sharp */ + COEF_3POINT_TRIANGLE, /* 3point_bspline */ + COEF_4POINT_TRIANGLE, /* 4point_bspline */ + COEF_3D_FILTER /* can not change */ +}; + +static unsigned int sharpness1_sr2_ctrl_32d7 = 0x00181008; +MODULE_PARM_DESC(sharpness1_sr2_ctrl_32d7, "sharpness1_sr2_ctrl_32d7"); +module_param(sharpness1_sr2_ctrl_32d7, uint, 0664); +/*0x3280 default val: 1920x1080*/ +static unsigned int sharpness1_sr2_ctrl_3280 = 0xffffffff; +MODULE_PARM_DESC(sharpness1_sr2_ctrl_3280, "sharpness1_sr2_ctrl_3280"); +module_param(sharpness1_sr2_ctrl_3280, uint, 0664); + +static unsigned int vpp_filter_fix; +MODULE_PARM_DESC(vpp_filter_fix, "vpp_filter_fix"); +module_param(vpp_filter_fix, uint, 0664); + +#define MAX_COEFF_LEVEL 5 +static uint num_coeff_level = MAX_COEFF_LEVEL; +static uint vert_coeff_settings[MAX_COEFF_LEVEL] = { + /* in:out */ + COEF_BICUBIC, + /* ratio < 1 */ + COEF_BICUBIC_SHARP, + /* ratio = 1 and phase = 0, */ + /* use for MBX without sharpness HW module, */ + /* TV use COEF_BICUBIC in function coeff */ + COEF_BICUBIC, + /* ratio in (1~0.5) */ + COEF_3POINT_BSPLINE, + /* ratio in [0.5~0.333) with pre-scaler on */ + /* this setting is sharpness/smooth balanced */ + /* if need more smooth(less sharp, could use */ + /* COEF_4POINT_BSPLINE or COEF_4POINT_TRIANGLE */ + COEF_4POINT_TRIANGLE, + /* ratio <= 0.333 with pre-scaler on */ + /* this setting is most smooth */ +}; + +static uint horz_coeff_settings[MAX_COEFF_LEVEL] = { + /* in:out */ + COEF_BICUBIC, + /* ratio < 1 */ + COEF_BICUBIC_SHARP, + /* ratio = 1 and phase = 0, */ + /* use for MBX without sharpness HW module, */ + /* TV use COEF_BICUBIC in function coeff */ + COEF_BICUBIC, + /* ratio in (1~0.5) */ + COEF_3POINT_BSPLINE, + /* ratio in [0.5~0.333) with pre-scaler on */ + /* this setting is sharpness/smooth balanced */ + /* if need more smooth(less sharp, could use */ + /* COEF_4POINT_BSPLINE or COEF_4POINT_TRIANGLE */ + COEF_4POINT_TRIANGLE, + /* ratio <= 0.333 with pre-scaler on */ + /* this setting is most smooth */ +}; + +static uint coeff(uint *settings, uint ratio, uint phase, + bool interlace, int combing_lev) +{ + uint coeff_select = 0; + uint coeff_type = 0; + + if (ratio >= (3 << 24)) + coeff_select = 4; + else if (ratio >= (2 << 24)) + coeff_select = 3; + else if (ratio > (1 << 24)) + coeff_select = 2; + else if (ratio == (1 << 24)) { + if (phase == 0) + coeff_select = 1; + else + coeff_select = 2; + } + coeff_type = settings[coeff_select]; + /* TODO: add future TV chips */ + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if (coeff_type == COEF_BICUBIC_SHARP) + coeff_type = COEF_BICUBIC; + } else { + /* + *gxtvbb use dejaggy in SR0 to reduce intelace combing + *other chip no dejaggy, need switch to more blur filter + */ + if (interlace && (coeff_select < 3) && vpp_filter_fix) + coeff_type = COEF_4POINT_BSPLINE; + /* use bicubic for static scene */ + if (combing_lev == 0) + coeff_type = COEF_BICUBIC; + } + return coeff_type; +} + +/* vertical and horizontal coeff settings */ +module_param_array(vert_coeff_settings, uint, &num_coeff_level, 0664); +MODULE_PARM_DESC(vert_coeff_settings, "\n vert_coeff_settings\n"); + +module_param_array(horz_coeff_settings, uint, &num_coeff_level, 0664); +MODULE_PARM_DESC(horz_coeff_settings, "\n horz_coeff_settings\n"); + +static bool vert_chroma_filter_en = true; +module_param(vert_chroma_filter_en, bool, 0664); +MODULE_PARM_DESC(vert_chroma_filter_en, "enable vertical chromafilter\n"); + +static bool vert_chroma_filter_force_en; +module_param(vert_chroma_filter_force_en, bool, 0664); +MODULE_PARM_DESC(vert_chroma_filter_force_en, + "force enable vertical chromafilter\n"); + +static uint vert_chroma_filter_limit = 480; +module_param(vert_chroma_filter_limit, uint, 0664); +MODULE_PARM_DESC(vert_chroma_filter_limit, "vertical chromafilter limit\n"); + +static uint num_chroma_filter = TOTAL_FILTERS; +module_param_array(chroma_filter_table, uint, &num_chroma_filter, 0664); +MODULE_PARM_DESC(chroma_filter_table, "\n chroma_filter_table\n"); + +static uint cur_vert_chroma_filter; +MODULE_PARM_DESC(cur_vert_chroma_filter, "cur_vert_chroma_filter"); +module_param(cur_vert_chroma_filter, int, 0444); + +static uint cur_vert_filter; +MODULE_PARM_DESC(cur_vert_filter, "cur_vert_filter"); +module_param(cur_vert_filter, int, 0444); + +static uint cur_horz_filter; +MODULE_PARM_DESC(cur_horz_filter, "cur_horz_filter"); +module_param(cur_horz_filter, int, 0444); + +static uint cur_skip_line; +MODULE_PARM_DESC(cur_skip_line, "cur_skip_line"); +module_param(cur_skip_line, int, 0444); + +static unsigned int super_scaler_v_ratio = 133; +MODULE_PARM_DESC(super_scaler_v_ratio, "super_scaler_v_ratio"); +module_param(super_scaler_v_ratio, uint, 0664); + +static u32 skip_policy = 0x81; +module_param(skip_policy, uint, 0664); +MODULE_PARM_DESC(skip_policy, "\n skip_policy\n"); + +static unsigned int scaler_filter_cnt_limit = 10; +MODULE_PARM_DESC(scaler_filter_cnt_limit, "scaler_filter_cnt_limit"); +module_param(scaler_filter_cnt_limit, uint, 0664); + +#ifdef TV_3D_FUNCTION_OPEN +static int force_filter_mode = 1; +MODULE_PARM_DESC(force_filter_mode, "force_filter_mode"); +module_param(force_filter_mode, int, 0664); +#endif +/*temp disable sr for power test*/ +bool super_scaler = true; +static unsigned int sr_support; +static u32 sr_reg_offt; +static u32 sr_reg_offt2; /*for tl1*/ +static unsigned int super_debug; +module_param(super_debug, uint, 0664); +MODULE_PARM_DESC(super_debug, "super_debug"); + +static unsigned int scaler_path_sel = SCALER_PATH_MAX; +module_param(scaler_path_sel, uint, 0664); +MODULE_PARM_DESC(scaler_path_sel, "scaler_path_sel"); + +static bool bypass_spscl0; +module_param(bypass_spscl0, bool, 0664); +MODULE_PARM_DESC(bypass_spscl0, "bypass_spscl0"); + +static bool bypass_spscl1; +module_param(bypass_spscl1, bool, 0664); +MODULE_PARM_DESC(bypass_spscl1, "bypass_spscl1"); + +static unsigned int vert_scaler_filter = 0xff; +module_param(vert_scaler_filter, uint, 0664); +MODULE_PARM_DESC(vert_scaler_filter, "vert_scaler_filter"); + +static unsigned int vert_chroma_scaler_filter = 0xff; +module_param(vert_chroma_scaler_filter, uint, 0664); +MODULE_PARM_DESC(vert_chroma_scaler_filter, "vert_chroma_scaler_filter"); + +static unsigned int horz_scaler_filter = 0xff; +module_param(horz_scaler_filter, uint, 0664); +MODULE_PARM_DESC(horz_scaler_filter, "horz_scaler_filter"); + +/*need check this value,*/ +static unsigned int bypass_ratio = 205; +module_param(bypass_ratio, uint, 0664); +MODULE_PARM_DESC(bypass_ratio, "bypass_ratio"); + +static unsigned int sr0_sr1_refresh = 1; +module_param(sr0_sr1_refresh, uint, 0664); +MODULE_PARM_DESC(sr0_sr1_refresh, "sr0_sr1_refresh"); + +static bool pre_scaler_en = true; +module_param(pre_scaler_en, bool, 0664); +MODULE_PARM_DESC(pre_scaler_en, "pre_scaler_en"); + +static unsigned int force_vskip_cnt; +MODULE_PARM_DESC(force_vskip_cnt, "force_vskip_cnt"); +module_param(force_vskip_cnt, uint, 0664); + +static unsigned int disable_adapted; +MODULE_PARM_DESC(disable_adapted, "disable_adapted"); +module_param(disable_adapted, uint, 0664); + +#define ZOOM_BITS 18 +#define PHASE_BITS 8 +/* + * when ratio for Y is 1:1 + * Line # In(P) In(I) Out(P) Out(I) Out(P) Out(I) + * 0 P_Y IT_Y P_Y IT_Y + * 1 P_Y IT_Y + * 2 IB_Y IB_Y + * 3 IB_Y + * 4 P_Y IT_Y P_Y IT_Y + * 5 P_Y IT_Y + * 6 IB_Y IB_Y + * 7 IB_Y + * 8 P_Y IT_Y P_Y IT_Y + * 9 P_Y IT_Y + * 10 IB_Y IB_Y + * 11 IB_Y + * 12 P_Y IT_Y P_Y IT_Y + * P_Y IT_Y + */ +/* + *The table data sequence here is arranged according to + * enum f2v_vphase_type_e enum, + * IT2IT, IB2IB, T2IB, IB2IT, P2IT, P2IB, IT2P, IB2P, P2P + */ +static const u8 f2v_420_in_pos[F2V_TYPE_MAX] = { 0, 2, 0, 2, 0, 0, 0, 2, 0 }; +static const u8 f2v_420_out_pos1[F2V_TYPE_MAX] = { 0, 2, 2, 0, 0, 2, 0, 0, 0 }; +static const u8 f2v_420_out_pos2[F2V_TYPE_MAX] = { 1, 3, 3, 1, 1, 3, 1, 1, 1 }; + +static void f2v_get_vertical_phase(u32 zoom_ratio, + u32 phase_adj, + struct f2v_vphase_s vphase[F2V_TYPE_MAX], + u32 interlace) +{ + enum f2v_vphase_type_e type; + s32 offset_in, offset_out; + s32 phase; + const u8 *f2v_420_out_pos; + + if ((interlace == 0) && (zoom_ratio > (1 << ZOOM_BITS))) + f2v_420_out_pos = f2v_420_out_pos2; + else + f2v_420_out_pos = f2v_420_out_pos1; + + for (type = F2V_IT2IT; type < F2V_TYPE_MAX; type++) { + offset_in = f2v_420_in_pos[type] << PHASE_BITS; + offset_out = + (f2v_420_out_pos[type] * zoom_ratio) >> (ZOOM_BITS - + PHASE_BITS); + + if (offset_in > offset_out) { + vphase[type].repeat_skip = -1; /* repeat line */ + vphase[type].phase = + ((4 << PHASE_BITS) + offset_out - offset_in) >> 2; + + } else { + vphase[type].repeat_skip = 0; /* skip line */ + + while ((offset_in + (4 << PHASE_BITS)) <= + offset_out) { + vphase[type].repeat_skip++; + offset_in += 4 << PHASE_BITS; + } + + vphase[type].phase = (offset_out - offset_in) >> 2; + } + + phase = vphase[type].phase + phase_adj; + + if (phase > 0x100) + vphase[type].repeat_skip++; + + vphase[type].phase = phase & 0xff; + + if (vphase[type].repeat_skip > 5) + vphase[type].repeat_skip = 5; + } +} + +/* + * V-shape non-linear mode + */ +static void calculate_non_linear_ratio( + unsigned int nonlinear_factor, + unsigned int middle_ratio, + unsigned int width_out, + struct vpp_frame_par_s *next_frame_par) +{ + unsigned int diff_ratio; + struct vppfilter_mode_s *vpp_filter = + &next_frame_par->vpp_filter; + + diff_ratio = middle_ratio * nonlinear_factor; + vpp_filter->vpp_hf_start_phase_step = (middle_ratio << 6) - diff_ratio; + vpp_filter->vpp_hf_start_phase_slope = diff_ratio * 4 / width_out; + vpp_filter->vpp_hf_end_phase_slope = + vpp_filter->vpp_hf_start_phase_slope | 0x1000000; + +} + +/* + *We find that the minimum line the video can be scaled + * down without skip line for different modes as below: + * 4k2k mode: + * video source minimus line ratio(height_in/height_out) + * 3840 * 2160 1690 1.278 + * 1920 * 1080 860 1.256 + * 1280 * 720 390 1.846 + * 720 * 480 160 3.000 + * 1080p mode: + * video source minimus line ratio(height_in/height_out) + * 3840 * 2160 840 2.571 + * 1920 * 1080 430 2.511 + * 1280 * 720 200 3.600 + * 720 * 480 80 6.000 + * So the safe scal ratio is 1.25 for 4K2K mode and 2.5 + * (1.25 * 3840 / 1920) for 1080p mode. + */ +#define MIN_RATIO_1000 1250 +static unsigned int min_skip_ratio = MIN_RATIO_1000; +MODULE_PARM_DESC(min_skip_ratio, "min_skip_ratio"); +module_param(min_skip_ratio, uint, 0664); +static unsigned int max_proc_height = 2160; +MODULE_PARM_DESC(max_proc_height, "max_proc_height"); +module_param(max_proc_height, uint, 0664); +static unsigned int cur_proc_height; +MODULE_PARM_DESC(cur_proc_height, "cur_proc_height"); +module_param(cur_proc_height, uint, 0444); +static unsigned int cur_skip_ratio; +MODULE_PARM_DESC(cur_skip_ratio, "cur_skip_ratio"); +module_param(cur_skip_ratio, uint, 0444); +static unsigned int cur_vf_type; +MODULE_PARM_DESC(cur_vf_type, "cur_vf_type"); +module_param(cur_vf_type, uint, 0444); +static unsigned int cur_freq_ratio; +MODULE_PARM_DESC(cur_freq_ratio, "cur_freq_ratio"); +module_param(cur_freq_ratio, uint, 0444); + +static unsigned int custom_ar; +MODULE_PARM_DESC(custom_ar, "custom_ar"); +module_param(custom_ar, uint, 0664); + +static unsigned int force_use_ext_ar; +MODULE_PARM_DESC(force_use_ext_ar, "force_use_ext_ar"); +module_param(force_use_ext_ar, uint, 0664); + +static unsigned int force_no_compress; +MODULE_PARM_DESC(force_no_compress, "force_no_compress"); +module_param(force_no_compress, uint, 0664); + +/* + *test on txlx: + *Time_out = (V_out/V_screen_total)/FPS_out; + *if di bypas: + *Time_in = (H_in * V_in)/Clk_vpu; + *if di work; for di clk is less than vpu usually; + *Time_in = (H_in * V_in)/Clk_di; + *if Time_in < Time_out,need do vskip; + *but in effect,test result may have some error. + *ratio1:V_out test result may larger than calc result; + *--after test is large ratio is 1.09; + *--so wo should choose the largest ratio_v_out = 110/100; + *ratio2:use clk_di or clk_vpu; + *--txlx di clk is 250M or 500M; + *--before txlx di clk is 333M; + *So need adjust bypass_ratio; + */ + +static int vpp_process_speed_check( + u32 layer_id, + s32 width_in, + s32 height_in, + s32 height_out, + s32 height_screen, + u32 video_speed_check_width, + u32 video_speed_check_height, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo, struct vframe_s *vf) +{ + u32 cur_ratio, bpp = 1; + int min_ratio_1000 = 0; + int freq_ratio = 1; + u32 sync_duration_den = 1; + u32 vtotal, htotal = 0, clk_in_pps = 0, clk_vpu = 0, clk_temp; + u32 input_time_us = 0, display_time_us = 0, dummy_time_us = 0; + u32 width_out = 0; + u32 vpu_clk = 0, max_height = 2160; /* 4k mode */ + + if (!vf) + return SPEED_CHECK_DONE; + + /* store the debug info for legacy */ + if (layer_id == 0) + cur_vf_type = vf->type; + + if (force_vskip_cnt == 0xff)/*for debug*/ + return SPEED_CHECK_DONE; + + if (next_frame_par->vscale_skip_count < force_vskip_cnt) + return SPEED_CHECK_VSKIP; + + if (vinfo->sync_duration_den > 0) + sync_duration_den = vinfo->sync_duration_den; + + if (vf->type & VIDTYPE_PRE_INTERLACE) { + if (is_meson_txlx_cpu()) + clk_in_pps = 250000000; + else + clk_in_pps = 333000000; + } else { + clk_in_pps = vpu_clk_get(); + } + + next_frame_par->clk_in_pps = clk_in_pps; + vpu_clk = vpu_clk_get(); + /* the output is only up to 1080p */ + if (vpu_clk <= 250000000) { + /* ((3840 * 2160) / 1920) * (vpu_clk / 1000000) / 666 */ + max_height = 4320 * (vpu_clk / 1000000) / 666; + } + + if (max_proc_height < max_height) + max_height = max_proc_height; + + cur_proc_height = max_height; + + if (width_in > 720) + min_ratio_1000 = min_skip_ratio; + else + min_ratio_1000 = 1750; + + if (vinfo->field_height < vinfo->height) + vtotal = vinfo->vtotal/2; + else + vtotal = vinfo->vtotal; + + /*according vlsi suggest, + *if di work need check mif input and vpu process speed + */ + if (vf->type & VIDTYPE_PRE_INTERLACE) { + htotal = vinfo->htotal; + clk_vpu = vpu_clk_get(); + clk_temp = clk_in_pps / 1000000; + if (clk_temp) + input_time_us = height_in * width_in / clk_temp; + clk_temp = clk_vpu / 1000000; + width_out = next_frame_par->VPP_hsc_endp - + next_frame_par->VPP_hsc_startp + 1; + if (clk_temp) + dummy_time_us = (vtotal * htotal - + height_out * width_out) / clk_temp; + display_time_us = 1000000 * sync_duration_den / + vinfo->sync_duration_num; + if (display_time_us > dummy_time_us) + display_time_us = display_time_us - dummy_time_us; + if (input_time_us > display_time_us) + return SPEED_CHECK_VSKIP; + } + + if ((vinfo->sync_duration_num / sync_duration_den) > 60) + freq_ratio = vinfo->sync_duration_num / + sync_duration_den / 60; + + if (freq_ratio < 1) + freq_ratio = 1; + cur_freq_ratio = freq_ratio; + + /* #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8) */ + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { + if ((width_in <= 0) || (height_in <= 0) || (height_out <= 0) + || (height_screen <= 0)) + return SPEED_CHECK_DONE; + + if ((next_frame_par->vscale_skip_count > 0) + && (vf->type & VIDTYPE_VIU_444)) + bpp = 2; + if (height_in * bpp > height_out) { + /* + *don't need do skip for under 5% scaler down + *reason:for 1080p input,4k output, if di clk is 250M, + *the clac height is 1119;which is bigger than 1080! + */ + if (height_in > height_out && + ((height_in - height_out) < height_in/20)) + return SPEED_CHECK_DONE; + if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXBB) { + cur_ratio = div_u64((u64)height_in * + (u64)vinfo->height * + 1000 * freq_ratio, + height_out * max_height); + /* di process first, need more a bit of ratio */ + if (vf->type & VIDTYPE_PRE_INTERLACE) + cur_ratio = (cur_ratio * 105) / 100; + if ((next_frame_par->vscale_skip_count > 0) + && (vf->type & VIDTYPE_VIU_444)) + cur_ratio = cur_ratio * 2; + + /* store the debug info for legacy */ + if (layer_id == 0) + cur_skip_ratio = cur_ratio; + + if ((cur_ratio > min_ratio_1000) && + (vf->source_type != + VFRAME_SOURCE_TYPE_TUNER) && + (vf->source_type != + VFRAME_SOURCE_TYPE_CVBS)) + return SPEED_CHECK_VSKIP; + } + if (vf->type & VIDTYPE_VIU_422) { + /*TODO vpu */ + if (height_out == 0 || + div_u64((u64)VPP_SPEED_FACTOR * + (u64)width_in * + (u64)height_in * + (u64)vinfo->sync_duration_num * + (u64)vtotal, + height_out * + sync_duration_den * + bypass_ratio) > clk_in_pps) + return SPEED_CHECK_VSKIP; + else + return SPEED_CHECK_DONE; + } else { + /*TODO vpu */ + if (height_out == 0 || + div_u64((u64)VPP_SPEED_FACTOR * + (u64)width_in * + (u64)height_in * + (u64)vinfo->sync_duration_num * + (u64)vtotal, + height_out * + sync_duration_den * 256) + > clk_in_pps) + return SPEED_CHECK_VSKIP; + /* 4K down scaling to non 4K > 30hz,*/ + /*skip lines for memory bandwidth */ + else if ((((vf->type & VIDTYPE_COMPRESS) + == 0) || (next_frame_par->nocomp)) + && (height_in > 2048) + && (height_out < 2048) + && (vinfo->sync_duration_num > + (30 * sync_duration_den)) + && (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXTVBB) + && (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXM)) + return SPEED_CHECK_VSKIP; + else + return SPEED_CHECK_DONE; + } + } else if (next_frame_par->hscale_skip_count == 0) { + /*TODO vpu */ + if (div_u64(VPP_SPEED_FACTOR * width_in * + vinfo->sync_duration_num * height_screen, + sync_duration_den * 256) + > vpu_clk_get()) + return SPEED_CHECK_HSKIP; + else + return SPEED_CHECK_DONE; + } + return SPEED_CHECK_DONE; + } + /* #else */ + /* return okay if vpp preblend enabled */ + + if ((READ_VCBUS_REG(VPP_MISC) & VPP_PREBLEND_EN) + && (READ_VCBUS_REG(VPP_MISC) & VPP_OSD1_PREBLEND)) + return SPEED_CHECK_DONE; + + /* #if (MESON_CPU_TYPE > MESON_CPU_TYPE_MESON6) */ + if (get_cpu_type() > MESON_CPU_MAJOR_ID_M6) { + if ((height_out + 1) > height_in) + return SPEED_CHECK_DONE; + } else { + /* #else */ + if (video_speed_check_width * video_speed_check_height * + height_out > height_screen * width_in * height_in) + return SPEED_CHECK_DONE; + } + /* #endif */ + amlog_mask(LOG_MASK_VPP, "%s failed\n", __func__); + return SPEED_CHECK_VSKIP; +} + +static int vpp_set_filters_internal( + struct disp_info_s *input, + u32 width_in, + u32 height_in, + u32 wid_out, + u32 hei_out, + const struct vinfo_s *vinfo, + u32 vpp_flags, + struct vpp_frame_par_s *next_frame_par, struct vframe_s *vf) +{ + u32 screen_width = 0, screen_height = 0; + s32 start, end; + s32 video_top, video_left, temp; + u32 video_width, video_height; + u32 ratio_x = 0; + u32 ratio_y = 0; + u32 tmp_ratio_y = 0; + int temp_width; + int temp_height; + struct vppfilter_mode_s *filter = &next_frame_par->vpp_filter; + u32 wide_mode; + s32 height_shift = 0; + u32 height_after_ratio; + u32 aspect_factor; + s32 ini_vphase; + u32 w_in = width_in; + u32 h_in = height_in; + bool h_crop_enable = false, v_crop_enable = false; + u32 width_out = wid_out; /* vinfo->width; */ + u32 height_out = hei_out; /* vinfo->height; */ + u32 aspect_ratio_out = + (vinfo->aspect_ratio_den << 10) / vinfo->aspect_ratio_num; + bool fill_match = true; + u32 orig_aspect = 0; + u32 screen_aspect = 0; + bool skip_policy_check = true; + u32 vskip_step; + s32 video_layer_global_offset_x, video_layer_global_offset_y; + u32 video_source_crop_top, video_source_crop_left; + u32 video_source_crop_bottom, video_source_crop_right; + u32 vpp_zoom_ratio, nonlinear_factor; + u32 speed_check_width, speed_check_height; + s32 video_layer_top, video_layer_left; + s32 video_layer_width, video_layer_height; + u32 cur_custom_ar; +#ifdef TV_REVERSE + bool reverse = false; +#endif + int ret = VppFilter_Success; + u32 vert_chroma_filter; + struct filter_info_s *cur_filter; + s32 vpp_zoom_center_x, vpp_zoom_center_y; + u32 crop_ratio = 1; + u32 crop_left, crop_right, crop_top, crop_bottom; + u32 sar_width = 0, sar_height = 0; + bool ext_sar = false; + bool no_compress = false; + + if (!input) + return VppFilter_Fail; + + cur_filter = &gfilter[input->layer_id]; + cur_custom_ar = input->custom_ar; + vpp_zoom_ratio = input->zoom_ratio; + vpp_zoom_center_x = input->zoom_center_x; + vpp_zoom_center_y = input->zoom_center_y; + speed_check_width = input->speed_check_width; + speed_check_height = input->speed_check_height; + nonlinear_factor = input->nonlinear_factor; + video_layer_global_offset_x = input->global_offset_x; + video_layer_global_offset_y = input->global_offset_y; + + video_layer_top = input->layer_top; + video_layer_left = input->layer_left; + video_layer_width = input->layer_width; + video_layer_height = input->layer_height; +#ifdef TV_REVERSE + reverse = input->reverse; +#endif + + if ((vf->type & VIDTYPE_MVC) || + (input->proc_3d_type & MODE_3D_ENABLE)) { + video_source_crop_left = 0; + video_source_crop_right = 0; + video_source_crop_top = 0; + video_source_crop_bottom = 0; + } else { + video_source_crop_left = input->crop_left; + video_source_crop_right = input->crop_right; + video_source_crop_top = input->crop_top; + video_source_crop_bottom = input->crop_bottom; + } + +#ifndef TV_3D_FUNCTION_OPEN + next_frame_par->vscale_skip_count = 0; + next_frame_par->hscale_skip_count = 0; +#endif + next_frame_par->nocomp = false; + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->vscale_skip_count++; + if (vpp_flags & VPP_FLAG_INTERLACE_OUT) + height_shift++; + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + vskip_step = 2; +#ifdef TV_3D_FUNCTION_OPEN + else if ((next_frame_par->vpp_3d_mode + == VPP_3D_MODE_LA) + && (input->proc_3d_type & MODE_3D_ENABLE)) + vskip_step = 2; +#endif + else + vskip_step = 1; + + if (super_debug) + pr_info("sar_width=%d, sar_height = %d, %d\n", + vf->sar_width, vf->sar_height, + force_use_ext_ar); + +RESTART_ALL: + crop_left = video_source_crop_left / crop_ratio; + crop_right = video_source_crop_right / crop_ratio; + crop_top = video_source_crop_top / crop_ratio; + crop_bottom = video_source_crop_bottom / crop_ratio; + + if (likely(w_in > + (crop_left + crop_right))) { + w_in -= crop_left; + w_in -= crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (crop_top + crop_bottom))) { + h_in -= crop_top; + h_in -= crop_bottom; + v_crop_enable = true; + } + +RESTART: + aspect_factor = (vpp_flags & VPP_FLAG_AR_MASK) >> VPP_FLAG_AR_BITS; + /* don't use input->wide_mode */ + wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + + if ((vpp_flags & VPP_FLAG_AR_MASK) == VPP_FLAG_AR_MASK) { + ext_sar = true; + sar_width = vf->sar_width; + sar_height = vf->sar_height; + } else if (force_use_ext_ar) { + ext_sar = true; + sar_width = 1; + sar_height = 1; + } + + if (ext_sar && sar_width && sar_height) { + aspect_factor = + div_u64((u64)256ULL * + (u64)sar_height * + (u64)height_in, + (u32)(sar_width * width_in)); + } else { + ext_sar = false; + } + + /* keep 8 bits resolution for aspect conversion */ + if (wide_mode == VIDEO_WIDEOPTION_4_3) { + if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) + aspect_factor = 0x155; + else + aspect_factor = 0xc0; + wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; + } else if (wide_mode == VIDEO_WIDEOPTION_16_9) { + if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) + aspect_factor = 0x1c7; + else + aspect_factor = 0x90; + wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; + } else if ((wide_mode >= VIDEO_WIDEOPTION_4_3_IGNORE) + && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { + if (aspect_factor != 0xc0) + fill_match = false; + + orig_aspect = aspect_factor; + screen_aspect = 0xc0; + ext_sar = false; + } else if ((wide_mode >= VIDEO_WIDEOPTION_16_9_IGNORE) + && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { + if (aspect_factor != 0x90) + fill_match = false; + + orig_aspect = aspect_factor; + screen_aspect = 0x90; + ext_sar = false; + } else if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { + if (cur_custom_ar != 0) { + aspect_factor = cur_custom_ar & 0x3ff; + ext_sar = false; + } + wide_mode = VIDEO_WIDEOPTION_NORMAL; + } else if (wide_mode == VIDEO_WIDEOPTION_AFD) { + if (aspect_factor == 0x90) { + wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; + ext_sar = false; + } else + wide_mode = VIDEO_WIDEOPTION_NORMAL; + } + /* if use the mode ar, will disable ext ar */ + + if (super_debug) + pr_info("aspect_factor=%d,%d,%d,%d,%d,%d\n", + aspect_factor, w_in, height_out, + width_out, h_in, aspect_ratio_out >> 2); + + if ((aspect_factor == 0) + || (aspect_factor == + (VPP_FLAG_AR_MASK >> VPP_FLAG_AR_BITS)) + || (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) + || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) { + aspect_factor = 0x100; + height_after_ratio = h_in; + } else if (ext_sar) { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * width_in) * aspect_ratio_out); + + tmp = tmp >> 2; + height_after_ratio = + div_u64((u64)256ULL * + (u64)w_in * + (u64)height_out * + (u64)sar_height * + (u64)height_in, + (u32)tmp); + height_after_ratio /= sar_height; + aspect_factor = (height_after_ratio << 8) / h_in; + } else { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * h_in) * aspect_ratio_out); + + tmp = tmp >> 2; + aspect_factor = + div_u64((unsigned long long)w_in * height_out * + (aspect_factor << 8), + (u32)tmp); + height_after_ratio = (h_in * aspect_factor) >> 8; + } + + /* + *if we have ever set a cropped display area for video layer + * (by checking video_layer_width/video_height), then + * it will override the input width_out/height_out for + * ratio calculations, a.k.a we have a window for video content + */ + video_top = video_layer_top; + video_left = video_layer_left; + video_width = video_layer_width; + video_height = video_layer_height; + if ((video_top == 0) && (video_left == 0) && (video_width <= 1) + && (video_height <= 1)) { + /* special case to do full screen display */ + video_width = width_out; + video_height = height_out; + } else { + if ((video_layer_width < 16) + && (video_layer_height < 16)) { + /* + *sanity check to move + *video out when the target size is too small + */ + video_width = width_out; + video_height = height_out; + video_left = width_out * 2; + } + video_top += video_layer_global_offset_y; + video_left += video_layer_global_offset_x; + } + + /*aspect ratio match */ + if ((wide_mode >= VIDEO_WIDEOPTION_4_3_IGNORE) + && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED) + && orig_aspect) { + if (vinfo->width && vinfo->height) + aspect_ratio_out = (vinfo->height << 10) / vinfo->width; + + if ((video_height << 10) > (video_width * aspect_ratio_out)) { + u32 real_video_height = + (video_width * aspect_ratio_out) >> 10; + + video_top += (video_height - real_video_height) >> 1; + video_height = real_video_height; + } else { + u32 real_video_width = + (video_height << 10) / aspect_ratio_out; + + video_left += (video_width - real_video_width) >> 1; + video_width = real_video_width; + } + + if (!fill_match) { + u32 screen_ratio_x, screen_ratio_y; + + screen_ratio_x = 1 << 18; + screen_ratio_y = (orig_aspect << 18) / screen_aspect; + + switch (wide_mode) { + case VIDEO_WIDEOPTION_4_3_LETTER_BOX: + case VIDEO_WIDEOPTION_16_9_LETTER_BOX: + screen_ratio_x = screen_ratio_y = + max(screen_ratio_x, screen_ratio_y); + break; + case VIDEO_WIDEOPTION_4_3_PAN_SCAN: + case VIDEO_WIDEOPTION_16_9_PAN_SCAN: + screen_ratio_x = screen_ratio_y = + min(screen_ratio_x, screen_ratio_y); + break; + case VIDEO_WIDEOPTION_4_3_COMBINED: + case VIDEO_WIDEOPTION_16_9_COMBINED: + screen_ratio_x = screen_ratio_y = + ((screen_ratio_x + screen_ratio_y) >> 1); + break; + default: + break; + } + + ratio_x = screen_ratio_x * w_in / video_width; + ratio_y = screen_ratio_y * h_in / orig_aspect * + screen_aspect / video_height; + } else { + screen_width = video_width * vpp_zoom_ratio / 100; + screen_height = video_height * vpp_zoom_ratio / 100; + + ratio_x = (w_in << 18) / screen_width; + ratio_y = (h_in << 18) / screen_height; + } + } else { + screen_width = video_width * vpp_zoom_ratio / 100; + screen_height = video_height * vpp_zoom_ratio / 100; + + ratio_x = (w_in << 18) / screen_width; + if (ratio_x * screen_width < (w_in << 18)) + ratio_x++; + + ratio_y = (height_after_ratio << 18) / screen_height; + if (super_debug) + pr_info("layer%d: height_after_ratio=%d,%d,%d,%d,%d\n", + input->layer_id, + height_after_ratio, ratio_x, ratio_y, + aspect_factor, wide_mode); + + if (wide_mode == VIDEO_WIDEOPTION_NORMAL) { + ratio_x = ratio_y = max(ratio_x, ratio_y); + ratio_y = (ratio_y << 8) / aspect_factor; + } else if (wide_mode == VIDEO_WIDEOPTION_NORMAL_NOSCALEUP) { + u32 r1, r2; + + r1 = max(ratio_x, ratio_y); + r2 = (r1 << 8) / aspect_factor; + + if ((r1 < (1 << 18)) || (r2 < (1 << 18))) { + if (r1 < r2) { + ratio_x = 1 << 18; + ratio_y = + (ratio_x << 8) / aspect_factor; + } else { + ratio_y = 1 << 18; + ratio_x = aspect_factor << 10; + } + } else { + ratio_x = r1; + ratio_y = r2; + } + } + } + + /* vertical */ + ini_vphase = vpp_zoom_center_y & 0xff; + + /* screen position for source */ + start = video_top + (video_height + 1) / 2 - + ((h_in << 17) + + (vpp_zoom_center_y << 10) + + (ratio_y >> 1)) / ratio_y; + end = ((h_in << 18) + (ratio_y >> 1)) / ratio_y + start - 1; + if (super_debug) + pr_info("layer%d: top:start =%d,%d,%d,%d %d,%d,%d\n", + input->layer_id, + start, end, video_top, + video_height, h_in, ratio_y, vpp_zoom_center_y); + +#ifdef TV_REVERSE + if (reverse) { + /* calculate source vertical clip */ + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } + temp = next_frame_par->VPP_vd_end_lines_ - + (video_height * ratio_y >> 18); + next_frame_par->VPP_vd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)); + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)) - video_top + 1; + } + temp = next_frame_par->VPP_vd_start_lines_ + + (temp_height * ratio_y >> 18); + next_frame_par->VPP_vd_end_lines_ = + (temp <= (h_in - 1)) ? temp : (h_in - 1); + } + + if (v_crop_enable) { + next_frame_par->VPP_vd_start_lines_ += crop_top; + next_frame_par->VPP_vd_end_lines_ += crop_top; + } + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->VPP_vd_start_lines_ &= ~1; + + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_pic_in_height_ / + (next_frame_par->vscale_skip_count + 1); + /* + *find overlapped region between + *[start, end], [0, height_out-1], + *[video_top, video_top+video_height-1] + */ + start = max(start, max(0, video_top)); + end = min(end, min((s32)(vinfo->height - 1), + (s32)(video_top + video_height - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_vsc_startp = 0; + next_frame_par->VPP_vsc_endp = 0; + } else { + next_frame_par->VPP_vsc_startp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (start >> 1) : start; + next_frame_par->VPP_vsc_endp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (end >> 1) : end; + } + + /* set filter co-efficients */ + tmp_ratio_y = ratio_y; + ratio_y <<= height_shift; + ratio_y = ratio_y / (next_frame_par->vscale_skip_count + 1); + + filter->vpp_vsc_start_phase_step = ratio_y << 6; + + f2v_get_vertical_phase(ratio_y, ini_vphase, + next_frame_par->VPP_vf_ini_phase_, + vpp_flags & VPP_FLAG_INTERLACE_OUT); + + /* horizontal */ + filter->vpp_hf_start_phase_slope = 0; + filter->vpp_hf_end_phase_slope = 0; + filter->vpp_hf_start_phase_step = ratio_x << 6; + + next_frame_par->VPP_hsc_linear_startp = next_frame_par->VPP_hsc_startp; + next_frame_par->VPP_hsc_linear_endp = next_frame_par->VPP_hsc_endp; + + filter->vpp_hsc_start_phase_step = ratio_x << 6; + next_frame_par->VPP_hf_ini_phase_ = vpp_zoom_center_x & 0xff; + + /* screen position for source */ + start = video_left + (video_width + 1) / 2 - ((w_in << 17) + + (vpp_zoom_center_x << 10) + + (ratio_x >> 1)) / ratio_x; + end = ((w_in << 18) + (ratio_x >> 1)) / ratio_x + start - 1; + if (super_debug) + pr_info("layer%d: left:start =%d,%d,%d,%d %d,%d,%d\n", + input->layer_id, + start, end, video_left, + video_width, w_in, ratio_x, vpp_zoom_center_x); + + /* calculate source horizontal clip */ +#ifdef TV_REVERSE + if (reverse) { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } + temp = next_frame_par->VPP_hd_end_lines_ - + (video_width * ratio_x >> 18); + next_frame_par->VPP_hd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)); + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)) - video_left + 1; + } + temp = next_frame_par->VPP_hd_start_lines_ + + (temp_width * ratio_x >> 18); + next_frame_par->VPP_hd_end_lines_ = + (temp <= (w_in - 1)) ? temp : (w_in - 1); + } + + if (h_crop_enable) { + next_frame_par->VPP_hd_start_lines_ += crop_left; + next_frame_par->VPP_hd_end_lines_ += crop_left; + } + + next_frame_par->VPP_line_in_length_ = + next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + /* + *find overlapped region between + * [start, end], [0, width_out-1], + * [video_left, video_left+video_width-1] + */ + start = max(start, max(0, video_left)); + end = min(end, + min((s32)(vinfo->width - 1), + (s32)(video_left + video_width - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_hsc_startp = 0; + next_frame_par->VPP_hsc_endp = 0; + /* avoid mif set wrong or di out size overflow */ + next_frame_par->VPP_hd_start_lines_ = 0; + next_frame_par->VPP_hd_end_lines_ = 0; + next_frame_par->VPP_line_in_length_ = 0; + } else { + next_frame_par->VPP_hsc_startp = start; + + next_frame_par->VPP_hsc_endp = end; + } + + if ((wide_mode == VIDEO_WIDEOPTION_NONLINEAR) && (end > start)) { + calculate_non_linear_ratio( + nonlinear_factor, + ratio_x, end - start, + next_frame_par); + next_frame_par->VPP_hsc_linear_startp = + next_frame_par->VPP_hsc_linear_endp = (start + end) / 2; + } + + /* + *check the painful bandwidth limitation and see + * if we need skip half resolution on source side for progressive + * frames. + */ + /* check vskip and hskip */ + if (((next_frame_par->vscale_skip_count < MAX_VSKIP_COUNT) + || !next_frame_par->hscale_skip_count) + && (!(vpp_flags & VPP_FLAG_VSCALE_DISABLE))) { + int skip = vpp_process_speed_check( + input->layer_id, + (next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1) / + (next_frame_par->hscale_skip_count + 1), + (next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1) / + (next_frame_par->vscale_skip_count + 1), + (next_frame_par->VPP_vsc_endp - + next_frame_par->VPP_vsc_startp + 1), + vinfo->height >> + ((vpp_flags & VPP_FLAG_INTERLACE_OUT) ? 1 : 0), + speed_check_width, + speed_check_height, + next_frame_par, + vinfo, + vf); + + if (skip == SPEED_CHECK_VSKIP) { + u32 next_vskip = + next_frame_par->vscale_skip_count + vskip_step; + + if (next_vskip <= MAX_VSKIP_COUNT) { + next_frame_par->vscale_skip_count = next_vskip; + goto RESTART; + } else + next_frame_par->hscale_skip_count = 1; + } else if (skip == SPEED_CHECK_HSKIP) + next_frame_par->hscale_skip_count = 1; + } + + if ((vf->type & VIDTYPE_COMPRESS) && + !(vf->type & VIDTYPE_NO_DW) && + (vf->canvas0Addr != 0) && + (!next_frame_par->nocomp)) { + if ((next_frame_par->vscale_skip_count > 1) + || !input->afbc_support + || force_no_compress) + no_compress = true; + } else + no_compress = false; + + if (no_compress) { + if ((vpp_flags & VPP_FLAG_MORE_LOG) + && input->afbc_support) + pr_info( + "layer%d: Try DW buffer for compressed frame scaling.\n", + input->layer_id); + + /* for VIDTYPE_COMPRESS, check if we can use double write + * buffer when primary frame can not be scaled. + */ + next_frame_par->nocomp = true; + w_in = width_in = vf->width; + h_in = height_in = vf->height; + next_frame_par->hscale_skip_count = 0; + next_frame_par->vscale_skip_count = 0; + crop_ratio = vf->compWidth / vf->width; + goto RESTART_ALL; + } + + if ((skip_policy & 0xf0) && (skip_policy_check == true)) { + skip_policy_check = false; + if (skip_policy & 0x40) { + next_frame_par->vscale_skip_count = skip_policy & 0xf; + goto RESTART; + } else if (skip_policy & 0x80) { + if ((((vf->width >= 4096) && + (!(vf->type & VIDTYPE_COMPRESS))) || + (vf->flag & VFRAME_FLAG_HIGH_BANDWIDTH)) + && (next_frame_par->vscale_skip_count == 0)) { + next_frame_par->vscale_skip_count = + skip_policy & 0xf; + goto RESTART; + } + } + } + + next_frame_par->video_input_h = next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->video_input_h = next_frame_par->video_input_h / + (next_frame_par->vscale_skip_count + 1); + next_frame_par->video_input_w = next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + next_frame_par->video_input_w = next_frame_par->video_input_w / + (next_frame_par->hscale_skip_count + 1); + + filter->vpp_hsc_start_phase_step = ratio_x << 6; + + /* coeff selection before skip and apply pre_scaler */ + filter->vpp_vert_filter = + coeff(vert_coeff_settings, + filter->vpp_vsc_start_phase_step * + (next_frame_par->vscale_skip_count + 1), + 1, + ((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE), + vf->combing_cur_lev); + + filter->vpp_vert_coeff = + filter_table[filter->vpp_vert_filter]; + + /* when local interlace or AV or ATV */ + /* TODO: add 420 check for local */ + if (vert_chroma_filter_force_en || (vert_chroma_filter_en + && (((vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) + && (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) + || (vf->height < vert_chroma_filter_limit))) + || (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) + || (vf->source_type == VFRAME_SOURCE_TYPE_TUNER)))) { + vert_chroma_filter = + chroma_filter_table[filter->vpp_vert_filter]; + filter->vpp_vert_chroma_coeff = + filter_table[vert_chroma_filter]; + filter->vpp_vert_chroma_filter_en = true; + } else { + vert_chroma_filter = COEF_NULL; + filter->vpp_vert_chroma_filter_en = false; + } + + /* avoid hscaler fitler adjustion affect on picture shift*/ + filter->vpp_horz_filter = + coeff(horz_coeff_settings, + filter->vpp_hf_start_phase_step, + next_frame_par->VPP_hf_ini_phase_, + ((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE), + vf->combing_cur_lev); + /*for gxl cvbs out index*/ + if ((vinfo->mode == VMODE_CVBS) && //DEBUG_TMP + (filter->vpp_hf_start_phase_step == (1 << 24))) + filter->vpp_horz_filter = COEF_BICUBIC_SHARP; + filter->vpp_horz_coeff = + filter_table[filter->vpp_horz_filter]; + + /* apply line skip */ + if (next_frame_par->hscale_skip_count) { + filter->vpp_hf_start_phase_step >>= 1; + filter->vpp_hsc_start_phase_step >>= 1; + next_frame_par->VPP_line_in_length_ >>= 1; + } + + /*pre hsc&vsc in pps for scaler down*/ + if ((filter->vpp_hf_start_phase_step >= 0x2000000) && + (filter->vpp_vsc_start_phase_step >= 0x2000000) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_GXBB) && + pre_scaler_en) { + filter->vpp_pre_vsc_en = 1; + filter->vpp_vsc_start_phase_step >>= 1; + ratio_y >>= 1; + f2v_get_vertical_phase(ratio_y, ini_vphase, + next_frame_par->VPP_vf_ini_phase_, + vpp_flags & VPP_FLAG_INTERLACE_OUT); + } else + filter->vpp_pre_vsc_en = 0; + + if ((filter->vpp_hf_start_phase_step >= 0x2000000) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_GXBB) && + pre_scaler_en) { + filter->vpp_pre_hsc_en = 1; + filter->vpp_hf_start_phase_step >>= 1; + filter->vpp_hsc_start_phase_step >>= 1; + } else + filter->vpp_pre_hsc_en = 0; + + next_frame_par->VPP_hf_ini_phase_ = vpp_zoom_center_x & 0xff; + + /* overwrite filter setting for interlace output*/ + /* TODO: not reasonable when 4K input to 480i output */ + if (vpp_flags & VPP_FLAG_INTERLACE_OUT) { + filter->vpp_vert_coeff = filter_table[COEF_BILINEAR]; + filter->vpp_vert_filter = COEF_BILINEAR; + } + + /* force overwrite filter setting */ + if (vert_scaler_filter <= COEF_3D_FILTER) { + filter->vpp_vert_coeff = filter_table[vert_scaler_filter]; + filter->vpp_vert_filter = vert_scaler_filter; + } + if (vert_chroma_filter_force_en && + (vert_chroma_scaler_filter <= COEF_3D_FILTER)) { + vert_chroma_filter = vert_chroma_scaler_filter; + filter->vpp_vert_chroma_coeff = + filter_table[vert_chroma_filter]; + filter->vpp_vert_chroma_filter_en = true; + } else { + vert_chroma_filter = COEF_NULL; + filter->vpp_vert_chroma_filter_en = false; + } + + if (horz_scaler_filter <= COEF_3D_FILTER) { + filter->vpp_horz_coeff = filter_table[horz_scaler_filter]; + filter->vpp_horz_filter = horz_scaler_filter; + } + +#ifdef TV_3D_FUNCTION_OPEN + /* final stage for 3D filter overwrite */ + if ((next_frame_par->vpp_3d_scale) && force_filter_mode) { + filter->vpp_vert_coeff = filter_table[COEF_3D_FILTER]; + filter->vpp_vert_filter = COEF_3D_FILTER; + } +#endif + + if ((cur_filter->last_vert_filter != filter->vpp_vert_filter) || + (cur_filter->last_horz_filter != filter->vpp_horz_filter)) { + cur_filter->last_vert_filter = filter->vpp_vert_filter; + cur_filter->last_horz_filter = filter->vpp_horz_filter; + cur_filter->scaler_filter_cnt = 0; + } else { + cur_filter->scaler_filter_cnt++; + } + if ((cur_filter->scaler_filter_cnt >= + scaler_filter_cnt_limit) && + ((cur_filter->cur_vert_filter != + filter->vpp_vert_filter) || + (cur_filter->cur_horz_filter != + filter->vpp_horz_filter))) { + cur_filter->cur_vert_filter = filter->vpp_vert_filter; + cur_filter->cur_horz_filter = filter->vpp_horz_filter; + cur_filter->scaler_filter_cnt = scaler_filter_cnt_limit; + ret = VppFilter_Success_and_Changed; + } + + /* store the debug info for legacy */ + if (input->layer_id == 0) { + cur_vert_filter = cur_filter->cur_vert_filter; + cur_horz_filter = cur_filter->cur_horz_filter; + cur_vert_chroma_filter = vert_chroma_filter; + cur_skip_line = + next_frame_par->vscale_skip_count; + } + + if ((next_frame_par->vscale_skip_count > 1) + && (vf->type & VIDTYPE_COMPRESS) + && (vf->type & VIDTYPE_NO_DW)) + ret = VppFilter_Changed_but_Hold; + return ret; +} +/* + *VPP_SRSHARP0_CTRL:0x1d91 + *[0]srsharp0 enable for sharpness module reg r/w + *[1]if sharpness is enable or vscaler is enable,must set to 1, + *sharpness1;reg can only to be w on gxtvbb;which is fix after txl + */ +int vpp_set_super_scaler_regs( + int scaler_path_sel, + int reg_srscl0_enable, + int reg_srscl0_hsize, + int reg_srscl0_vsize, + int reg_srscl0_hori_ratio, + int reg_srscl0_vert_ratio, + int reg_srscl1_enable, + int reg_srscl1_hsize, + int reg_srscl1_vsize, + int reg_srscl1_hori_ratio, + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height) +{ + + int tmp_data = 0; + int tmp_data2 = 0; + unsigned int data_path_chose; + int sr_core0_max_width = SUPER_CORE0_WIDTH_MAX; + + /* just work around for g12a not to disable sr core2 bit2 */ + if (is_meson_g12a_cpu() && (reg_srscl0_vert_ratio == 0)) + sr_core0_max_width = SUPER_CORE0_WIDTH_MAX << 1; + + /* top config */ + tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP0_CTRL); + if (sr0_sr1_refresh) { + if (reg_srscl0_hsize > sr_core0_max_width) { + if (((tmp_data >> 1) & 0x1) != 0) + VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, + 0, 1, 1); + } else { + if (((tmp_data >> 1) & 0x1) != 1) + VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, + 1, 1, 1); + } + if ((tmp_data & 0x1) != 1) + VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 1, 0, 1); + } + tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP1_CTRL); + if (sr0_sr1_refresh) { + if (((tmp_data >> 1) & 0x1) != 1) + VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP1_CTRL, 1, 1, 1); + if ((tmp_data & 0x1) != 1) + VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP1_CTRL, 1, 0, 1); + } + /* core0 config */ + tmp_data = VSYNC_RD_MPEG_REG( + SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt); + if (sr0_sr1_refresh) { + if (((tmp_data >> 5) & 0x1) != (reg_srscl0_vert_ratio&0x1)) + VSYNC_WR_MPEG_REG_BITS( + SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, + reg_srscl0_vert_ratio&0x1, 5, 1); + if (((tmp_data >> 4) & 0x1) != (reg_srscl0_hori_ratio&0x1)) + VSYNC_WR_MPEG_REG_BITS( + SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, + reg_srscl0_hori_ratio&0x1, 4, 1); + + if (reg_srscl0_hsize > sr_core0_max_width) { + if (((tmp_data >> 2) & 0x1) != 0) + VSYNC_WR_MPEG_REG_BITS( + SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, + 0, 2, 1); + } else { + if (((tmp_data >> 2) & 0x1) != 1) { + if (is_meson_txlx_cpu()) + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SR2_CTRL + + sr_reg_offt, + 1, 2, 1); + VSYNC_WR_MPEG_REG_BITS( + SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, + 1, 2, 1); + } + } + + if ((tmp_data & 0x1) == (reg_srscl0_hori_ratio & 0x1)) + VSYNC_WR_MPEG_REG_BITS( + SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, + ((~(reg_srscl0_hori_ratio & 0x1)) & 0x1), 0, 1); + } + /* core1 config */ + if (sr_support & SUPER_CORE1_SUPPORT) { + if (is_meson_gxtvbb_cpu()) + tmp_data = sharpness1_sr2_ctrl_32d7; + else + tmp_data = VSYNC_RD_MPEG_REG( + SRSHARP1_SHARP_SR2_CTRL + + sr_reg_offt2); /*0xc80*/ + if (is_meson_gxtvbb_cpu() || + (((tmp_data >> 5) & 0x1) != + (reg_srscl1_vert_ratio & 0x1)) || + (((tmp_data >> 4) & 0x1) != + (reg_srscl1_hori_ratio & 0x1)) || + ((tmp_data & 0x1) == + (reg_srscl1_hori_ratio & 0x1)) || + (((tmp_data >> 2) & 0x1) != 1)) { + tmp_data = tmp_data & (~(1 << 5)); + tmp_data = tmp_data & (~(1 << 4)); + tmp_data = tmp_data & (~(1 << 2)); + tmp_data = tmp_data & (~(1 << 0)); + tmp_data |= ((reg_srscl1_vert_ratio & 0x1) << 5); + tmp_data |= ((reg_srscl1_hori_ratio & 0x1) << 4); + tmp_data |= (1 << 2); + tmp_data |= + (((~(reg_srscl1_hori_ratio & 0x1)) & 0x1) << 0); + if (sr0_sr1_refresh) { + VSYNC_WR_MPEG_REG( + SRSHARP1_SHARP_SR2_CTRL + + sr_reg_offt2, /*0xc80*/ + tmp_data); + sharpness1_sr2_ctrl_32d7 = tmp_data; + } + } + } + + /* size config */ + tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | + (reg_srscl0_vsize & 0x1fff); + tmp_data2 = VSYNC_RD_MPEG_REG( + SRSHARP0_SHARP_HVSIZE + sr_reg_offt); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG( + SRSHARP0_SHARP_HVSIZE + sr_reg_offt, + tmp_data); + + tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | + (reg_srscl1_vsize & 0x1fff); + + if (sr_support & SUPER_CORE1_SUPPORT) { + if (get_cpu_type() != MESON_CPU_MAJOR_ID_GXTVBB) + tmp_data2 = VSYNC_RD_MPEG_REG( + SRSHARP1_SHARP_HVSIZE + sr_reg_offt2); + if (is_meson_gxtvbb_cpu() || (tmp_data != tmp_data2)) { + VSYNC_WR_MPEG_REG( + SRSHARP1_SHARP_HVSIZE + sr_reg_offt2, tmp_data); + if (is_meson_gxtvbb_cpu()) + sharpness1_sr2_ctrl_3280 = tmp_data; + } + } + + /*ve input size setting*/ + if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) + tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | + (reg_srscl0_vsize & 0x1fff); + else if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) && + ((scaler_path_sel == PPS_CORE0_CORE1) || + (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1))) + tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | + (reg_srscl0_vsize & 0x1fff); + else + tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | + (reg_srscl1_vsize & 0x1fff); + tmp_data2 = VSYNC_RD_MPEG_REG(VPP_VE_H_V_SIZE); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG(VPP_VE_H_V_SIZE, tmp_data); + /*chroma blue stretch size setting*/ + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() + || (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))) { + tmp_data = (((vpp_postblend_out_width & 0x1fff) << 16) | + (vpp_postblend_out_height & 0x1fff)); + VSYNC_WR_MPEG_REG(VPP_OUT_H_V_SIZE, tmp_data); + } else { + if (scaler_path_sel == CORE0_PPS_CORE1) { + tmp_data = (((reg_srscl1_hsize & 0x1fff) << + reg_srscl1_hori_ratio) << 16) | + ((reg_srscl1_vsize & 0x1fff) << + reg_srscl1_vert_ratio); + tmp_data2 = VSYNC_RD_MPEG_REG(VPP_PSR_H_V_SIZE); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG(VPP_PSR_H_V_SIZE, tmp_data); + } else if ((scaler_path_sel == CORE0_CORE1_PPS) || + (scaler_path_sel == CORE1_BEFORE_PPS) || + (scaler_path_sel == CORE1_AFTER_PPS)) { + tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | + (reg_srscl1_vsize & 0x1fff); + tmp_data2 = VSYNC_RD_MPEG_REG(VPP_PSR_H_V_SIZE); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG(VPP_PSR_H_V_SIZE, tmp_data); + } + } + + /* path config */ + if (is_meson_txhd_cpu()) + data_path_chose = 6; + else + data_path_chose = 5; + if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXHD) { + if ((scaler_path_sel == CORE0_PPS_CORE1) || + (scaler_path_sel == CORE1_BEFORE_PPS) || + (scaler_path_sel == CORE0_BEFORE_PPS)) { + VSYNC_WR_MPEG_REG_BITS(VPP_VE_ENABLE_CTRL, + 0, data_path_chose, 1); + } else { + VSYNC_WR_MPEG_REG_BITS(VPP_VE_ENABLE_CTRL, + 1, data_path_chose, 1); + } + } + if (super_scaler == 0) { + VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0); + VSYNC_WR_MPEG_REG(VPP_SRSHARP1_CTRL, 0); + } + + return 0; +} + +static void vpp_set_super_scaler( + u32 vpp_wide_mode, + const struct vinfo_s *vinfo, + struct vpp_frame_par_s *next_frame_par, + bool bypass_sr0, bool bypass_sr1) +{ + unsigned int hor_sc_multiple_num, ver_sc_multiple_num, temp; + u32 width_out = next_frame_par->VPP_hsc_endp - + next_frame_par->VPP_hsc_startp + 1; + u32 height_out = next_frame_par->VPP_vsc_endp - + next_frame_par->VPP_vsc_startp + 1; + u32 src_width = next_frame_par->video_input_w; + u32 src_height = next_frame_par->video_input_h; + u32 sr_path; + + /*for sr adjust*/ + vpp_super_scaler_support(); + + next_frame_par->sr_core_support = sr_support; + + hor_sc_multiple_num = (1 << PPS_FRAC_BITS) / + next_frame_par->vpp_filter.vpp_hsc_start_phase_step; + ver_sc_multiple_num = SUPER_SCALER_V_FACTOR*(1 << PPS_FRAC_BITS)/ + next_frame_par->vpp_filter.vpp_vsc_start_phase_step; + + /* just calcuate the enable sclaer module */ + /* + *note:if first check h may cause v can't do scaling; + * for example: 1920x1080(input),3840x2160(output); + * todo:if you have better idea,you can improve it + */ + /* step1: judge core0&core1 vertical enable or disable*/ + if (ver_sc_multiple_num >= 2*SUPER_SCALER_V_FACTOR) { + next_frame_par->supsc0_vert_ratio = + ((src_width < SUPER_CORE0_WIDTH_MAX / 2) && + (sr_support & SUPER_CORE0_SUPPORT)) ? 1 : 0; + next_frame_par->supsc1_vert_ratio = + ((width_out < SUPER_CORE1_WIDTH_MAX) && + (src_width < SUPER_CORE1_WIDTH_MAX / 2) && + (sr_support & SUPER_CORE1_SUPPORT)) ? 1 : 0; + if (next_frame_par->supsc0_vert_ratio && + (ver_sc_multiple_num < 4 * SUPER_SCALER_V_FACTOR)) + next_frame_par->supsc1_vert_ratio = 0; + next_frame_par->supsc0_enable = + next_frame_par->supsc0_vert_ratio ? 1 : 0; + next_frame_par->supsc1_enable = + next_frame_par->supsc1_vert_ratio ? 1 : 0; + } else { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_vert_ratio = 0; + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_vert_ratio = 0; + } + /* step2: judge core0&core1 horizontal enable or disable*/ + if ((hor_sc_multiple_num >= 2) && + (vpp_wide_mode != VIDEO_WIDEOPTION_NONLINEAR)) { + if ((src_width > SUPER_CORE0_WIDTH_MAX) || + ((src_width > SUPER_CORE0_WIDTH_MAX / 2) && + next_frame_par->supsc0_vert_ratio) || + (((src_width << 1) > SUPER_CORE1_WIDTH_MAX / 2) && + next_frame_par->supsc1_vert_ratio)) + next_frame_par->supsc0_hori_ratio = 0; + else if (sr_support & SUPER_CORE0_SUPPORT) + next_frame_par->supsc0_hori_ratio = 1; + if (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX) || + (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX / 2) && + next_frame_par->supsc1_vert_ratio) || + (next_frame_par->supsc0_hori_ratio && + (hor_sc_multiple_num < 4))) + next_frame_par->supsc1_hori_ratio = 0; + else if (sr_support & SUPER_CORE1_SUPPORT) + next_frame_par->supsc1_hori_ratio = 1; + next_frame_par->supsc0_enable = + (next_frame_par->supsc0_hori_ratio || + next_frame_par->supsc0_enable) ? 1 : 0; + next_frame_par->supsc1_enable = + (next_frame_par->supsc1_hori_ratio || + next_frame_par->supsc1_enable) ? 1 : 0; + } else { + next_frame_par->supsc0_enable = + next_frame_par->supsc0_vert_ratio ? 1 : 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc1_enable = + next_frame_par->supsc1_vert_ratio ? 1 : 0; + next_frame_par->supsc1_hori_ratio = 0; + } + /*double check core1 input width for core1_vert_ratio!!!*/ + if (next_frame_par->supsc1_vert_ratio && + (width_out >> next_frame_par->supsc1_hori_ratio > + SUPER_CORE1_WIDTH_MAX/2)) { + next_frame_par->supsc1_vert_ratio = 0; + if (next_frame_par->supsc1_hori_ratio == 0) + next_frame_par->supsc1_enable = 0; + } + /* option add patch */ + if ((ver_sc_multiple_num <= super_scaler_v_ratio) && + (src_height >= SUPER_CORE0_WIDTH_MAX / 2) && + (src_height <= 1088) && + (ver_sc_multiple_num > SUPER_SCALER_V_FACTOR) && + (vinfo->height >= 2000)) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc1_enable = 1; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc1_hori_ratio = 1; + next_frame_par->supsc0_vert_ratio = 0; + next_frame_par->supsc1_vert_ratio = 1; + } + if (bypass_sr0 || !(sr_support & SUPER_CORE0_SUPPORT)) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + } + + /* much vskip case, no need super scale up */ + if (next_frame_par->vscale_skip_count >= 2) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + } + + if (bypass_sr1 || !(sr_support & SUPER_CORE1_SUPPORT)) { + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_hori_ratio = 0; + next_frame_par->supsc1_vert_ratio = 0; + } + /* new add according to pq test @20170808 on gxlx*/ + if (scaler_path_sel >= SCALER_PATH_MAX) { + if (is_meson_gxlx_cpu()) { + if (next_frame_par->supsc1_hori_ratio && + next_frame_par->supsc1_vert_ratio) + next_frame_par->supscl_path = CORE1_BEFORE_PPS; + else + next_frame_par->supscl_path = CORE1_AFTER_PPS; + } else if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { + next_frame_par->supscl_path = CORE0_BEFORE_PPS; + } else + next_frame_par->supscl_path = CORE0_PPS_CORE1; + } else + next_frame_par->supscl_path = scaler_path_sel; + + /*patch for width align 2*/ + if (super_scaler && (width_out%2) && + ((((next_frame_par->supscl_path == CORE0_AFTER_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio) || + (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || + (next_frame_par->supscl_path == CORE0_CORE1_PPS) || + (next_frame_par->supscl_path == CORE1_AFTER_PPS) || + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_hori_ratio))) { + temp = next_frame_par->VPP_hsc_endp; + if (++temp >= vinfo->width) { + if ((next_frame_par->VPP_hsc_startp > 0) && + (next_frame_par->VPP_hsc_startp < + next_frame_par->VPP_hsc_endp)) + next_frame_par->VPP_hsc_startp--; + else if (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio && + next_frame_par->supsc1_hori_ratio) { + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_hori_ratio = 0; + next_frame_par->supsc1_vert_ratio = 0; + next_frame_par->VPP_hsc_endp++; + } else if ((next_frame_par->supscl_path == + CORE0_AFTER_PPS) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio)) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + } else if ((next_frame_par->supscl_path == + CORE1_AFTER_PPS) || + (next_frame_par->supscl_path == + CORE0_PPS_CORE1) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_hori_ratio)) { + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_hori_ratio = 0; + next_frame_par->supsc1_vert_ratio = 0; + } + } else + next_frame_par->VPP_hsc_endp++; + width_out++; + } + + /*patch for height align 2*/ + if (super_scaler && (height_out%2) && + ((((next_frame_par->supscl_path == CORE0_AFTER_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio) || + (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || + (next_frame_par->supscl_path == CORE0_CORE1_PPS) || + (next_frame_par->supscl_path == CORE1_AFTER_PPS) || + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_vert_ratio))) { + temp = next_frame_par->VPP_vsc_endp; + if (++temp >= vinfo->height) { + if ((next_frame_par->VPP_vsc_startp > 0) && + (next_frame_par->VPP_vsc_startp < + next_frame_par->VPP_vsc_endp)) + next_frame_par->VPP_vsc_startp--; + else if (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio && + next_frame_par->supsc1_vert_ratio) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + next_frame_par->VPP_vsc_endp++; + } else if ((next_frame_par->supscl_path == + CORE0_AFTER_PPS) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio)) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + } else if ((next_frame_par->supscl_path == + CORE1_AFTER_PPS) || + (next_frame_par->supscl_path == + CORE0_PPS_CORE1) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_vert_ratio)) { + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_hori_ratio = 0; + next_frame_par->supsc1_vert_ratio = 0; + } + } else + next_frame_par->VPP_vsc_endp++; + height_out++; + } + + /* select the scaler path:[core0 =>> + *ppscaler =>> core1] or + *[core0 =>> ppscaler =>> postblender =>> core1] + *gxlx only have core1,so the path:[core1 ==> pps ==> postblend] + *or pps ==> core1 ==> postblend + *txhd only have core0,so the path:[core0 ==> pps ==> postblend] + *or pps ==> core0 ==> postblend + */ + if (next_frame_par->supscl_path == CORE0_AFTER_PPS) { + next_frame_par->spsc0_h_in = + height_out >> next_frame_par->supsc0_vert_ratio; + next_frame_par->spsc0_w_in = + width_out >> next_frame_par->supsc0_hori_ratio; + } else if ((next_frame_par->supscl_path == PPS_CORE0_CORE1) + || (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)){ /*tl1*/ + next_frame_par->spsc0_h_in = + (height_out >> next_frame_par->supsc0_vert_ratio) >> + next_frame_par->supsc1_vert_ratio; + next_frame_par->spsc0_w_in = + (width_out >> next_frame_par->supsc0_hori_ratio) >> + next_frame_par->supsc1_hori_ratio; + } else { + next_frame_par->spsc0_h_in = src_height; + next_frame_par->spsc0_w_in = src_width; + } + if ((next_frame_par->supscl_path == CORE0_PPS_CORE1) || + (next_frame_par->supscl_path == CORE0_CORE1_PPS) || + (next_frame_par->supscl_path == CORE1_AFTER_PPS) || + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) { + next_frame_par->spsc1_h_in = + (height_out >> next_frame_par->supsc1_vert_ratio); + next_frame_par->spsc1_w_in = + (width_out >> next_frame_par->supsc1_hori_ratio); + } else if (next_frame_par->supscl_path == CORE1_BEFORE_PPS) { + next_frame_par->spsc1_h_in = src_height; + next_frame_par->spsc1_w_in = src_width; + } else if (next_frame_par->supscl_path == CORE0_AFTER_PPS) { + next_frame_par->spsc1_h_in = + (height_out >> next_frame_par->supsc0_vert_ratio); + next_frame_par->spsc1_w_in = + (width_out >> next_frame_par->supsc0_hori_ratio); + } else { + next_frame_par->spsc1_h_in = height_out; + next_frame_par->spsc1_w_in = width_out; + } + /*recalc phase step and pps input&output size param*/ + /*phase*/ + if (next_frame_par->supsc0_hori_ratio) { + next_frame_par->vpp_filter.vpp_hsc_start_phase_step <<= 1; + next_frame_par->vpp_filter.vpp_hf_start_phase_step <<= 1; + } + if (next_frame_par->supsc1_hori_ratio) { + next_frame_par->vpp_filter.vpp_hsc_start_phase_step <<= 1; + next_frame_par->vpp_filter.vpp_hf_start_phase_step <<= 1; + } + if (next_frame_par->supsc0_vert_ratio) + next_frame_par->vpp_filter.vpp_vsc_start_phase_step <<= 1; + if (next_frame_par->supsc1_vert_ratio) + next_frame_par->vpp_filter.vpp_vsc_start_phase_step <<= 1; + /*pps input size*/ + if (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || + (next_frame_par->supscl_path == CORE0_CORE1_PPS) || + (next_frame_par->supscl_path == CORE0_BEFORE_PPS))) { + next_frame_par->VPP_line_in_length_ <<= + next_frame_par->supsc0_hori_ratio; + next_frame_par->VPP_pic_in_height_ <<= + next_frame_par->supsc0_vert_ratio; + } + if (((next_frame_par->supscl_path == CORE0_CORE1_PPS) || + (next_frame_par->supscl_path == CORE1_BEFORE_PPS))) { + next_frame_par->VPP_line_in_length_ <<= + next_frame_par->supsc1_hori_ratio; + next_frame_par->VPP_pic_in_height_ <<= + next_frame_par->supsc1_vert_ratio; + } + + sr_path = next_frame_par->supscl_path; + /* path config */ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + if (sr_path == CORE0_PPS_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } else if (sr_path == PPS_CORE0_CORE1) { + next_frame_par->sr0_position = 0; + next_frame_par->sr1_position = 1; + } else if (sr_path == + PPS_CORE0_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 0; + next_frame_par->sr1_position = 0; + } else if (sr_path == + CORE0_PPS_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } + } else if (is_meson_txhd_cpu() + || is_meson_g12a_cpu() + || is_meson_g12b_cpu() + || is_meson_sm1_cpu()) { + if (sr_path == CORE0_BEFORE_PPS) + next_frame_par->sr0_position = 1; + else if (sr_path == CORE0_AFTER_PPS) + next_frame_par->sr0_position = 0; + else + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else if (is_meson_gxlx_cpu()) { + if (sr_path == CORE1_BEFORE_PPS) + next_frame_par->sr1_position = 1; + else if (sr_path == CORE1_AFTER_PPS) + next_frame_par->sr1_position = 0; + else + next_frame_par->sr1_position = 1; + next_frame_par->sr0_position = 0; + } else if (is_meson_txlx_cpu() + || is_meson_txl_cpu() + || is_meson_gxtvbb_cpu()) { + if (sr_path == CORE0_PPS_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } else if (sr_path == + CORE0_PPS_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } + } + + if (super_debug) { + pr_info("layer0: spsc0_w_in=%u, spsc0_h_in=%u, spsc1_w_in=%u, spsc1_h_in=%u.\n", + next_frame_par->spsc0_w_in, next_frame_par->spsc0_h_in, + next_frame_par->spsc1_w_in, next_frame_par->spsc1_h_in); + pr_info("layer0: supsc0_hori=%d,supsc1_hori=%d,supsc0_v=%d,supsc1_v=%d\n", + next_frame_par->supsc0_hori_ratio, + next_frame_par->supsc1_hori_ratio, + next_frame_par->supsc0_vert_ratio, + next_frame_par->supsc1_vert_ratio); + pr_info("layer0: VPP_hd_start_lines= %d,%d,%d,%d, %d,%d,%d,%d, %d,%d\n", + next_frame_par->VPP_hd_start_lines_, + next_frame_par->VPP_hd_end_lines_, + next_frame_par->VPP_vd_start_lines_, + next_frame_par->VPP_vd_end_lines_, + next_frame_par->VPP_hsc_startp, + next_frame_par->VPP_hsc_endp, + next_frame_par->VPP_hsc_linear_startp, + next_frame_par->VPP_hsc_linear_endp, + next_frame_par->VPP_vsc_startp, + next_frame_par->VPP_vsc_endp); + } +} + +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) +void get_vpp_3d_mode( + u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) +{ + switch (trans_fmt) { + case TVIN_TFMT_3D_LRH_OLOR: + case TVIN_TFMT_3D_LRH_OLER: + case TVIN_TFMT_3D_LRH_ELOR: + case TVIN_TFMT_3D_LRH_ELER: + case TVIN_TFMT_3D_DET_LR: + *vpp_3d_mode = VPP_3D_MODE_LR; + break; + case TVIN_TFMT_3D_FP: + case TVIN_TFMT_3D_TB: + case TVIN_TFMT_3D_DET_TB: + case TVIN_TFMT_3D_FA: + *vpp_3d_mode = VPP_3D_MODE_TB; + if (process_3d_type & MODE_3D_MVC) + *vpp_3d_mode = VPP_3D_MODE_FA; + break; + case TVIN_TFMT_3D_LA: + case TVIN_TFMT_3D_DET_INTERLACE: + *vpp_3d_mode = VPP_3D_MODE_LA; + break; + case TVIN_TFMT_3D_DET_CHESSBOARD: + default: + *vpp_3d_mode = VPP_3D_MODE_NULL; + break; + } +} + +static void vpp_get_video_source_size( + u32 *src_width, u32 *src_height, + u32 process_3d_type, struct vframe_s *vf, + struct vpp_frame_par_s *next_frame_par) +{ + int frame_width, frame_height; + + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } + if ((process_3d_type & MODE_3D_AUTO) || + (((process_3d_type & MODE_3D_TO_2D_R) || + (process_3d_type & MODE_3D_TO_2D_L) || + (process_3d_type & MODE_3D_LR_SWITCH) || + (process_3d_type & MODE_FORCE_3D_TO_2D_TB) || + (process_3d_type & MODE_FORCE_3D_TO_2D_LR)) && + (process_3d_type & MODE_3D_ENABLE))) { + if (vf->trans_fmt) { + if (process_3d_type & MODE_3D_TO_2D_MASK) + *src_height = vf->left_eye.height; + else { + *src_height = vf->left_eye.height << 1; + next_frame_par->vpp_2pic_mode = 1; + } + *src_width = vf->left_eye.width; + } + + switch (vf->trans_fmt) { + case TVIN_TFMT_3D_LRH_OLOR: + case TVIN_TFMT_3D_LRH_OLER: + case TVIN_TFMT_3D_LRH_ELOR: + case TVIN_TFMT_3D_LRH_ELER: + case TVIN_TFMT_3D_DET_LR: + next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; + break; + case TVIN_TFMT_3D_FP: + case TVIN_TFMT_3D_TB: + case TVIN_TFMT_3D_DET_TB: + case TVIN_TFMT_3D_FA: + next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; + /*just for mvc 3d file */ + if (process_3d_type & MODE_3D_MVC) { + next_frame_par->vpp_2pic_mode = 2; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; + } + break; + case TVIN_TFMT_3D_LA: + case TVIN_TFMT_3D_DET_INTERLACE: + next_frame_par->vpp_3d_mode = VPP_3D_MODE_LA; + next_frame_par->vpp_2pic_mode = 0; + break; + case TVIN_TFMT_3D_DET_CHESSBOARD: + default: + *src_width = frame_width; + *src_height = frame_height; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; + next_frame_par->vpp_3d_scale = 0; + next_frame_par->vpp_2pic_mode = 0; + break; + } + + } else if ((process_3d_type & MODE_3D_LR) || + (process_3d_type & MODE_FORCE_3D_LR)) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; + if (process_3d_type & MODE_3D_TO_2D_MASK) { + *src_width = frame_width >> 1; + *src_height = frame_height; + } else if (process_3d_type & MODE_3D_OUT_LR) { + *src_width = frame_width; + *src_height = frame_height; + next_frame_par->vpp_2pic_mode = 1; + } else { + *src_width = frame_width >> 1; + *src_height = frame_height << 1; + next_frame_par->vpp_2pic_mode = 1; + } + + } else if ((process_3d_type & MODE_3D_TB) || + (process_3d_type & MODE_FORCE_3D_TB)) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; + if (process_3d_type & MODE_3D_TO_2D_MASK) { + *src_width = frame_width; + *src_height = frame_height >> 1; + } else if (process_3d_type & MODE_3D_OUT_LR) { + *src_width = frame_width << 1; + *src_height = frame_height >> 1; + next_frame_par->vpp_2pic_mode = 1; + } else { + *src_width = frame_width; + *src_height = frame_height; + next_frame_par->vpp_2pic_mode = 1; + } + if (process_3d_type & MODE_3D_MVC) { + *src_width = frame_width; + *src_height = frame_height << 1; + next_frame_par->vpp_2pic_mode = 2; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; + } + } else if (process_3d_type & MODE_3D_LA) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_LA; + *src_height = frame_height - 1; + *src_width = frame_width; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 1; + if (process_3d_type & MODE_3D_TO_2D_MASK) { + next_frame_par->vscale_skip_count = 1; + next_frame_par->vpp_3d_scale = 0; + } else if (process_3d_type & MODE_3D_OUT_TB) { + *src_height = frame_height << 1; + next_frame_par->vscale_skip_count = 1; + next_frame_par->vpp_3d_scale = 0; + } else if (process_3d_type & MODE_3D_OUT_LR) { + *src_width = frame_width << 1; + next_frame_par->vscale_skip_count = 1; + next_frame_par->vpp_3d_scale = 0; + } + } else if ((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_LR) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) { + + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; + if (process_3d_type & MODE_3D_TO_2D_MASK) { + if (process_3d_type & MODE_FORCE_3D_FA_TB) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; + *src_width = frame_width; + *src_height = frame_height >> 1; + } + if (process_3d_type & MODE_FORCE_3D_FA_LR) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; + *src_width = frame_width >> 1; + *src_height = frame_height; + } + if (process_3d_type & MODE_3D_MVC) { + *src_width = frame_width; + *src_height = frame_height; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; + } + if (vf->trans_fmt == TVIN_TFMT_3D_FP) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; + *src_width = frame_width; + *src_height = vf->left_eye.height; + } + next_frame_par->vpp_2pic_mode = 0; + } else if (process_3d_type & MODE_3D_OUT_LR) { + *src_width = frame_width << 1; + *src_height = frame_height; + next_frame_par->vpp_2pic_mode = 2; + } else { + *src_width = frame_width; + *src_height = frame_height << 1; + next_frame_par->vpp_2pic_mode = 2; + } + } else { + *src_width = frame_width; + *src_height = frame_height; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 0; + } + /*process 3d->2d or l/r switch case */ + if ((next_frame_par->vpp_3d_mode != VPP_3D_MODE_NULL) && + (next_frame_par->vpp_3d_mode != VPP_3D_MODE_LA) + && (process_3d_type & MODE_3D_ENABLE)) { + if (process_3d_type & MODE_3D_TO_2D_R) + next_frame_par->vpp_2pic_mode = VPP_SELECT_PIC1; + else if (process_3d_type & MODE_3D_TO_2D_L) + next_frame_par->vpp_2pic_mode = VPP_SELECT_PIC0; + else if (process_3d_type & MODE_3D_LR_SWITCH) + next_frame_par->vpp_2pic_mode |= VPP_PIC1_FIRST; + if ((process_3d_type & MODE_FORCE_3D_TO_2D_LR) || + (process_3d_type & MODE_FORCE_3D_TO_2D_TB)) + next_frame_par->vpp_2pic_mode = VPP_SELECT_PIC0; + + /*only display one pic */ + if ((next_frame_par->vpp_2pic_mode & 0x3) == 0) + next_frame_par->vpp_3d_scale = 0; + else + next_frame_par->vpp_3d_scale = 1; + } + /*avoid dividing 0 error */ + if (*src_width == 0 || *src_height == 0) { + *src_width = frame_width; + *src_height = frame_height; + } +} +#endif + +static int vpp_set_filters_no_scaler_internal( + struct disp_info_s *input, + u32 width_in, + u32 height_in, + u32 wid_out, + u32 hei_out, + const struct vinfo_s *vinfo, + u32 vpp_flags, + struct vpp_frame_par_s *next_frame_par, struct vframe_s *vf) +{ + s32 start, end; + s32 video_top, video_left, temp; + u32 video_width, video_height; + u32 ratio_x = 0; + u32 ratio_y = 0; + u32 ratio_tmp = 0; + int temp_width; + int temp_height; + struct vppfilter_mode_s *filter = &next_frame_par->vpp_filter; + u32 wide_mode; + s32 height_shift = 0; + u32 w_in = width_in; + u32 h_in = height_in; + bool h_crop_enable = false, v_crop_enable = false; + bool skip_policy_check = true; + u32 vskip_step; + s32 video_layer_global_offset_x, video_layer_global_offset_y; + u32 video_source_crop_top, video_source_crop_left; + u32 video_source_crop_bottom, video_source_crop_right; + s32 video_layer_top, video_layer_left; + s32 video_layer_width, video_layer_height; +#ifdef TV_REVERSE + bool reverse = false; +#endif + int ret = VppFilter_Success; + u32 crop_ratio = 1; + u32 crop_left, crop_right, crop_top, crop_bottom; + bool no_compress = false; + + if (!input) + return VppFilter_Fail; + + video_layer_global_offset_x = input->global_offset_x; + video_layer_global_offset_y = input->global_offset_y; + + video_layer_top = input->layer_top; + video_layer_left = input->layer_left; + video_layer_width = input->layer_width; + video_layer_height = input->layer_height; +#ifdef TV_REVERSE + reverse = input->reverse; +#endif + + if ((vf->type & VIDTYPE_MVC) || + (input->proc_3d_type & MODE_3D_ENABLE)) { + video_source_crop_left = 0; + video_source_crop_right = 0; + video_source_crop_top = 0; + video_source_crop_bottom = 0; + } else { + video_source_crop_left = input->crop_left; + video_source_crop_right = input->crop_right; + video_source_crop_top = input->crop_top; + video_source_crop_bottom = input->crop_bottom; + } + + next_frame_par->vscale_skip_count = 0; + next_frame_par->hscale_skip_count = 0; + next_frame_par->nocomp = false; + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->vscale_skip_count++; + if (vpp_flags & VPP_FLAG_INTERLACE_OUT) + height_shift++; + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + vskip_step = 2; + else + vskip_step = 1; + +RESTART_ALL: + crop_left = video_source_crop_left / crop_ratio; + crop_right = video_source_crop_right / crop_ratio; + crop_top = video_source_crop_top / crop_ratio; + crop_bottom = video_source_crop_bottom / crop_ratio; + + if (likely(w_in > + (crop_left + crop_right))) { + w_in -= crop_left; + w_in -= crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (crop_top + crop_bottom))) { + h_in -= crop_top; + h_in -= crop_bottom; + v_crop_enable = true; + } + +RESTART: + /* don't use input->wide_mode */ + wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + + /* + *if we have ever set a cropped display area for video layer + * (by checking video_layer_width/video_height), then + * it will override the input width_out/height_out for + * ratio calculations, a.k.a we have a window for video content + */ + video_top = video_layer_top; + video_left = video_layer_left; + video_width = video_layer_width; + video_height = video_layer_height; + if ((video_top == 0) && (video_left == 0) && (video_width <= 1) + && (video_height <= 1)) { + /* special case to do full screen display */ + video_width = video_layer_width; + video_height = video_layer_height; + } else { + video_top += video_layer_global_offset_y; + video_left += video_layer_global_offset_x; + } + + ratio_x = (1 << 18); + ratio_y = (1 << 18); + + /* screen position for source */ + start = video_top + (video_height + 1) / 2 - + ((h_in << 17) + + (ratio_y >> 1)) / ratio_y; + end = ((h_in << 18) + (ratio_y >> 1)) / ratio_y + start - 1; + if (super_debug) + pr_info("layer%d: top:start =%d,%d,%d,%d %d,%d\n", + input->layer_id, + start, end, video_top, + video_height, h_in, ratio_y); + +#ifdef TV_REVERSE + if (reverse) { + /* calculate source vertical clip */ + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } + temp = next_frame_par->VPP_vd_end_lines_ - + (video_height * ratio_y >> 18); + next_frame_par->VPP_vd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)); + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)) - video_top + 1; + } + temp = next_frame_par->VPP_vd_start_lines_ + + (temp_height * ratio_y >> 18); + next_frame_par->VPP_vd_end_lines_ = + (temp <= (h_in - 1)) ? temp : (h_in - 1); + } + + if (v_crop_enable) { + next_frame_par->VPP_vd_start_lines_ += crop_top; + next_frame_par->VPP_vd_end_lines_ += crop_top; + } + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->VPP_vd_start_lines_ &= ~1; + + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_pic_in_height_ / + (next_frame_par->vscale_skip_count + 1); + /* + *find overlapped region between + *[start, end], [0, height_out-1], + *[video_top, video_top+video_height-1] + */ + start = max(start, max(0, video_top)); + end = min(end, min((s32)(vinfo->height - 1), + (s32)(video_top + video_height - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_vsc_startp = 0; + next_frame_par->VPP_vsc_endp = 0; + } else { + next_frame_par->VPP_vsc_startp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (start >> 1) : start; + next_frame_par->VPP_vsc_endp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (end >> 1) : end; + } + + /* set filter co-efficients */ + ratio_y <<= height_shift; + ratio_tmp = ratio_y / (next_frame_par->vscale_skip_count + 1); + ratio_y = ratio_tmp; + + filter->vpp_vsc_start_phase_step = 0x1000000; + + /* horizontal */ + filter->vpp_hf_start_phase_slope = 0; + filter->vpp_hf_end_phase_slope = 0; + filter->vpp_hf_start_phase_step = 0x1000000; + + next_frame_par->VPP_hsc_linear_startp = next_frame_par->VPP_hsc_startp; + next_frame_par->VPP_hsc_linear_endp = next_frame_par->VPP_hsc_endp; + + filter->vpp_hsc_start_phase_step = 0x1000000; + next_frame_par->VPP_hf_ini_phase_ = 0; + + /* screen position for source */ + start = video_left + (video_width + 1) / 2 - + ((w_in << 17) + (ratio_x >> 1)) / ratio_x; + end = ((w_in << 18) + (ratio_x >> 1)) / ratio_x + start - 1; + if (super_debug) + pr_info("layer%d: left:start =%d,%d,%d,%d %d,%d\n", + input->layer_id, + start, end, video_left, + video_width, w_in, ratio_x); + + /* calculate source horizontal clip */ +#ifdef TV_REVERSE + if (reverse) { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } + temp = next_frame_par->VPP_hd_end_lines_ - + (video_width * ratio_x >> 18); + next_frame_par->VPP_hd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)); + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)) - video_left + 1; + } + temp = next_frame_par->VPP_hd_start_lines_ + + (temp_width * ratio_x >> 18); + next_frame_par->VPP_hd_end_lines_ = + (temp <= (w_in - 1)) ? temp : (w_in - 1); + } + + if (h_crop_enable) { + next_frame_par->VPP_hd_start_lines_ += crop_left; + next_frame_par->VPP_hd_end_lines_ += crop_left; + } + + next_frame_par->VPP_line_in_length_ = + next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + /* + *find overlapped region between + * [start, end], [0, width_out-1], + * [video_left, video_left+video_width-1] + */ + start = max(start, max(0, video_left)); + end = min(end, + min((s32)(vinfo->width - 1), + (s32)(video_left + video_width - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_hsc_startp = 0; + next_frame_par->VPP_hsc_endp = 0; + /* avoid mif set wrong or di out size overflow */ + next_frame_par->VPP_hd_start_lines_ = 0; + next_frame_par->VPP_hd_end_lines_ = 0; + next_frame_par->VPP_line_in_length_ = 0; + } else { + next_frame_par->VPP_hsc_startp = start; + next_frame_par->VPP_hsc_endp = end; + } + + /* + *check the painful bandwidth limitation and see + * if we need skip half resolution on source side for progressive + * frames. + */ + /* check vskip and hskip */ + if (((next_frame_par->vscale_skip_count < MAX_VSKIP_COUNT) + || !next_frame_par->hscale_skip_count) + && (!(vpp_flags & VPP_FLAG_VSCALE_DISABLE))) { + int skip = SPEED_CHECK_DONE; + + if (skip == SPEED_CHECK_VSKIP) { + u32 next_vskip = + next_frame_par->vscale_skip_count + vskip_step; + + if (next_vskip <= MAX_VSKIP_COUNT) { + next_frame_par->vscale_skip_count = next_vskip; + goto RESTART; + } else + next_frame_par->hscale_skip_count = 1; + } else if (skip == SPEED_CHECK_HSKIP) + next_frame_par->hscale_skip_count = 1; + } + + if ((vf->type & VIDTYPE_COMPRESS) && + !(vf->type & VIDTYPE_NO_DW) && + (vf->canvas0Addr != 0) && + (!next_frame_par->nocomp)) { + if ((next_frame_par->vscale_skip_count > 1) + || !input->afbc_support + || force_no_compress) + no_compress = true; + } else + no_compress = false; + + if (no_compress) { + if ((vpp_flags & VPP_FLAG_MORE_LOG) + && input->afbc_support) + pr_info( + "layer%d: Try DW buffer for compressed frame scaling.\n", + input->layer_id); + + /* for VIDTYPE_COMPRESS, check if we can use double write + * buffer when primary frame can not be scaled. + */ + next_frame_par->nocomp = true; + w_in = width_in = vf->width; + h_in = height_in = vf->height; + next_frame_par->hscale_skip_count = 0; + next_frame_par->vscale_skip_count = 0; + if (vf->width && vf->compWidth) + crop_ratio = vf->compWidth / vf->width; + goto RESTART_ALL; + } + + if ((skip_policy & 0xf0) && (skip_policy_check == true)) { + skip_policy_check = false; + if (skip_policy & 0x40) { + next_frame_par->vscale_skip_count = skip_policy & 0xf; + goto RESTART; + } else if (skip_policy & 0x80) { + if ((((vf->width >= 4096) && + (!(vf->type & VIDTYPE_COMPRESS))) || + (vf->flag & VFRAME_FLAG_HIGH_BANDWIDTH)) + && (next_frame_par->vscale_skip_count == 0)) { + next_frame_par->vscale_skip_count = + skip_policy & 0xf; + goto RESTART; + } + } + } + + next_frame_par->video_input_h = next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->video_input_h = next_frame_par->video_input_h / + (next_frame_par->vscale_skip_count + 1); + next_frame_par->video_input_w = next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + next_frame_par->video_input_w = next_frame_par->video_input_w / + (next_frame_par->hscale_skip_count + 1); + + filter->vpp_hsc_start_phase_step = 0x1000000; + + /* apply line skip */ + if (next_frame_par->hscale_skip_count) { + filter->vpp_hf_start_phase_step >>= 1; + filter->vpp_hsc_start_phase_step >>= 1; + next_frame_par->VPP_line_in_length_ >>= 1; + } + + if ((next_frame_par->vscale_skip_count > 1) + && (vf->type & VIDTYPE_COMPRESS) + && (vf->type & VIDTYPE_NO_DW)) + ret = VppFilter_Changed_but_Hold; + return ret; +} + +int vpp_set_filters( + struct disp_info_s *input, + struct vframe_s *vf, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo, + bool bypass_sr, u32 op_flag) +{ + u32 src_width = 0; + u32 src_height = 0; + u32 vpp_flags = 0; + u32 aspect_ratio = 0; + u32 process_3d_type; + u32 wide_mode; + int ret = VppFilter_Fail; + struct disp_info_s local_input; + + if (!input) + return ret; + + WARN_ON(vinfo == NULL); + + /* use local var to avoid the input data be overwritten */ + memcpy(&local_input, input, sizeof(struct disp_info_s)); + + process_3d_type = local_input.proc_3d_type; + wide_mode = local_input.wide_mode; + + next_frame_par->VPP_post_blend_vd_v_start_ = 0; + next_frame_par->VPP_post_blend_vd_h_start_ = 0; + + next_frame_par->VPP_postproc_misc_ = 0x200; + next_frame_par->vscale_skip_count = 0; + next_frame_par->hscale_skip_count = 0; + + if (vf->type & VIDTYPE_COMPRESS) { + src_width = vf->compWidth; + src_height = vf->compHeight; + } else { + src_width = vf->width; + src_height = vf->height; + } + +#if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) + /* + *check 3d mode change in display buffer or 3d type + *get the source size according to 3d mode + */ + if (local_input.layer_id == 0) { + if (process_3d_type & MODE_3D_ENABLE) { + vpp_get_video_source_size( + &src_width, &src_height, + process_3d_type, + vf, next_frame_par); + } else { + next_frame_par->vpp_3d_mode = + VPP_3D_MODE_NULL; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 0; + } + next_frame_par->trans_fmt = vf->trans_fmt; + get_vpp_3d_mode(process_3d_type, + next_frame_par->trans_fmt, + &next_frame_par->vpp_3d_mode); + if (local_input.vpp_3d_scale) + next_frame_par->vpp_3d_scale = 1; + } else { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 0; + next_frame_par->trans_fmt = vf->trans_fmt; + } + amlog_mask(LOG_MASK_VPP, "%s: src_width %u,src_height %u.\n", __func__, + src_width, src_height); +#endif + /* check force ratio change flag in display buffer also + * if it exist then it will override the settings in display side + */ + if (vf->ratio_control & DISP_RATIO_FORCECONFIG) { + if ((vf->ratio_control & DISP_RATIO_CTRL_MASK) == + DISP_RATIO_KEEPRATIO) { + if (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) + wide_mode = VIDEO_WIDEOPTION_NORMAL; + } else { + if (wide_mode == VIDEO_WIDEOPTION_NORMAL) + wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; + } + if (vf->ratio_control & DISP_RATIO_FORCE_NORMALWIDE) + wide_mode = VIDEO_WIDEOPTION_NORMAL; + else if (vf->ratio_control & DISP_RATIO_FORCE_FULL_STRETCH) + wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; + } + + aspect_ratio = (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) + >> DISP_RATIO_ASPECT_RATIO_BIT; + + /* the height from vdin afbc will be half */ + /* so need no interlace in */ + if ((vf->type & VIDTYPE_INTERLACE) + && !(vf->type & VIDTYPE_COMPRESS)) + vpp_flags = VPP_FLAG_INTERLACE_IN; + + if (vf->ratio_control & DISP_RATIO_PORTRAIT_MODE) + vpp_flags |= VPP_FLAG_PORTRAIT_MODE; + + if (vf->type & VIDTYPE_VSCALE_DISABLE) + vpp_flags |= VPP_FLAG_VSCALE_DISABLE; + + if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) + && !disable_adapted) { + if (vf->pic_mode.screen_mode != 0xff) + wide_mode = vf->pic_mode.screen_mode; + + if (vf->pic_mode.AFD_enable + && (vf->ratio_control & DISP_RATIO_INFOFRAME_AVAIL)) + wide_mode = VIDEO_WIDEOPTION_AFD; + if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { + if (!custom_ar) + local_input.custom_ar = custom_ar; + else + local_input.custom_ar = + vf->pic_mode.custom_ar; + } + if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { + /* from wss, need add global setting */ + local_input.crop_top += vf->pic_mode.vs; + local_input.crop_left += vf->pic_mode.hs; + local_input.crop_bottom += vf->pic_mode.ve; + local_input.crop_right += vf->pic_mode.he; + } else { + /* from PQ database, final setting */ + local_input.crop_top = vf->pic_mode.vs; + local_input.crop_left = vf->pic_mode.hs; + local_input.crop_bottom = vf->pic_mode.ve; + local_input.crop_right = vf->pic_mode.he; + } + } + + if (!local_input.pps_support) + wide_mode = VIDEO_WIDEOPTION_NORMAL; + + /* don't restore the wide mode */ + /* input->wide_mode = wide_mode; */ + vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); + + if (vinfo->field_height != vinfo->height) + vpp_flags |= VPP_FLAG_INTERLACE_OUT; + + if (op_flag & 1) + vpp_flags |= VPP_FLAG_MORE_LOG; + + next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; + next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; + next_frame_par->VPP_post_blend_h_size_ = vinfo->width; + + if (local_input.pps_support) + ret = vpp_set_filters_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); + else + ret = vpp_set_filters_no_scaler_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); + + /* bypass sr since the input w/h may be wrong */ + if (ret == VppFilter_Changed_but_Hold) + bypass_sr = true; + /*config super scaler after set next_frame_par is calc ok for pps*/ + if (local_input.layer_id == 0) + vpp_set_super_scaler( + wide_mode, + vinfo, next_frame_par, + (bypass_sr | bypass_spscl0), + (bypass_sr | bypass_spscl1)); + return ret; +} + +s32 vpp_set_nonlinear_factor( + struct disp_info_s *info, u32 f) +{ + if (f < MAX_NONLINEAR_FACTOR) { + info->nonlinear_factor = f; + return 0; + } + return -1; +} + +u32 vpp_get_nonlinear_factor( + struct disp_info_s *info) +{ + return info->nonlinear_factor; +} + +void vpp_disp_info_init( + struct disp_info_s *info, u8 id) +{ + if (info) { + memset(info, 0, sizeof(struct disp_info_s)); + info->nonlinear_factor = MAX_NONLINEAR_FACTOR / 2; + info->zoom_ratio = 100; + info->speed_check_width = 1800; + info->speed_check_height = 1400; + info->layer_id = id; + memset(&gfilter[id], 0, sizeof(struct filter_info_s)); + } +} + +void vpp_super_scaler_support(void) +{ + if (is_meson_gxlx_cpu()) { + sr_support &= ~SUPER_CORE0_SUPPORT; + sr_support |= SUPER_CORE1_SUPPORT; + } else if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { + sr_support |= SUPER_CORE0_SUPPORT; + sr_support &= ~SUPER_CORE1_SUPPORT; + } else if (is_meson_gxtvbb_cpu() + || is_meson_txl_cpu() + || is_meson_txlx_cpu() + || is_meson_tl1_cpu() + || is_meson_tm2_cpu()) { + sr_support |= SUPER_CORE0_SUPPORT; + sr_support |= SUPER_CORE1_SUPPORT; + } else { + sr_support &= ~SUPER_CORE0_SUPPORT; + sr_support &= ~SUPER_CORE1_SUPPORT; + } + if (super_scaler == 0) { + sr_support &= ~SUPER_CORE0_SUPPORT; + sr_support &= ~SUPER_CORE1_SUPPORT; + } + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { + sr_reg_offt = 0xc00; + sr_reg_offt2 = 0x00; + } else if (is_meson_tl1_cpu() + || is_meson_tm2_cpu()) { + sr_reg_offt = 0xc00; + sr_reg_offt2 = 0xc80; + } else { + sr_reg_offt = 0; + sr_reg_offt2 = 0x00; + } +} +/*for gxlx only have core1 which will affact pip line*/ +void vpp_bypass_ratio_config(void) +{ + if (is_meson_gxbb_cpu() || is_meson_gxl_cpu() || + is_meson_gxm_cpu()) + bypass_ratio = 125; + else if (is_meson_txlx_cpu()) + /*change from 247 to 210 for bandwidth @20180627*/ + bypass_ratio = 210; + else if (is_meson_txl_cpu()) + bypass_ratio = 247;/*0x110 * (100/110)=0xf7*/ + else + bypass_ratio = 205; +} + + diff --git a/include/linux/amlogic/media/frame_sync/tsync.h b/include/linux/amlogic/media/frame_sync/tsync.h index 51f5ea0..bc43f0f 100644 --- a/include/linux/amlogic/media/frame_sync/tsync.h +++ b/include/linux/amlogic/media/frame_sync/tsync.h @@ -154,4 +154,6 @@ static inline int get_vsync_pts_inc_mode(void) { return 0; } static inline void set_pts_realign(void) { return; } #endif +u32 timestamp_get_pcrlatency(void); +bool tsync_check_vpts_discontinuity(unsigned int vpts); #endif /* TSYNC_H */ diff --git a/include/linux/amlogic/media/registers/cpu_version.h b/include/linux/amlogic/media/registers/cpu_version.h index 48cbb15..b2483c0 100644 --- a/include/linux/amlogic/media/registers/cpu_version.h +++ b/include/linux/amlogic/media/registers/cpu_version.h @@ -32,6 +32,8 @@ #define MESON_CPU_MAJOR_ID_MG9TV 0x1C #define MESON_CPU_MAJOR_ID_M8M2 0x1D +#define MESON_CPU_VERSION_LVL_PACK 2 + enum meson_cpuid_type_e { MESON_CPU_MAJOR_ID_M8B = 0x1B, MESON_CPU_MAJOR_ID_GXBB = 0x1F, @@ -45,7 +47,9 @@ enum meson_cpuid_type_e { MESON_CPU_MAJOR_ID_TXHD, MESON_CPU_MAJOR_ID_G12A, MESON_CPU_MAJOR_ID_G12B, - MESON_CPU_MAJOR_ID_TL1, + MESON_CPU_MAJOR_ID_SM1 = 0x2B, + MESON_CPU_MAJOR_ID_TL1 = 0x2E, + MESON_CPU_MAJOR_ID_TM2, MESON_CPU_MAJOR_ID_UNKNOWN, }; @@ -55,11 +59,40 @@ struct codecio_device_data_s { extern struct codecio_device_data_s codecio_meson_dev; +#ifdef CONFIG_AMLOGIC_CPU_VERSION +int get_meson_cpu_version(int level); +int arch_big_cpu(int cpu); +#else +static inline int get_meson_cpu_version(int level) +{ + return -1; +} + +static inline int arch_big_cpu(int cpu) +{ + return 0; +} +#endif + static inline int get_cpu_type(void) { return codecio_meson_dev.cpu_id; } +static inline u32 get_cpu_package(void) +{ + unsigned int pk; + + pk = get_meson_cpu_version(MESON_CPU_VERSION_LVL_PACK) & 0xF0; + return pk; +} + +static inline bool package_id_is(unsigned int id) +{ + return get_cpu_package() == id; +} + + static inline bool is_meson_m8_cpu(void) { return get_cpu_type() == MESON_CPU_MAJOR_ID_M8; @@ -141,13 +174,29 @@ static inline bool is_meson_g12b_cpu(void) return get_cpu_type() == MESON_CPU_MAJOR_ID_G12B; } +static inline bool is_meson_sm1_cpu(void) +{ + return get_cpu_type() == MESON_CPU_MAJOR_ID_SM1; +} + static inline bool is_meson_tl1_cpu(void) { return get_cpu_type() == MESON_CPU_MAJOR_ID_TL1; } +static inline bool is_meson_tm2_cpu(void) +{ + return get_cpu_type() == MESON_CPU_MAJOR_ID_TM2; +} + static inline bool cpu_after_eq(unsigned int id) { return get_cpu_type() >= id; } + +static inline bool is_meson_txlx_package_962X(void) +{ + return is_meson_txlx_cpu() && package_id_is(0x10); +} + #endif diff --git a/include/linux/amlogic/media/registers/regs/vpp_regs.h b/include/linux/amlogic/media/registers/regs/vpp_regs.h index ebef3d9..271fb11 100644 --- a/include/linux/amlogic/media/registers/regs/vpp_regs.h +++ b/include/linux/amlogic/media/registers/regs/vpp_regs.h @@ -180,6 +180,9 @@ #define VPP_CLIP_MISC0 0x1dd9 #define VPP_CLIP_MISC1 0x1dda +#define VPP_VD1_CLIP_MISC0 0x1de1 +#define VPP_VD1_CLIP_MISC1 0x1de2 + #define VPP2_MISC 0x1e26 #define VPP2_OFIFO_SIZE 0x1e27 #define VPP2_INT_LINE_NUM 0x1e20 diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 3178dd1..9c02605 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -37,6 +37,8 @@ #define VIDTYPE_VD2 0x800000 #define VIDTYPE_COMPRESS_LOSS 0x1000000 #define VIDTYPE_COMB_MODE 0x2000000 +#define VIDTYPE_NO_DW 0x4000000 +#define VIDTYPE_SUPPORT_COMPRESS 0x8000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 @@ -400,6 +402,9 @@ struct vframe_s { struct vframe_pic_mode_s pic_mode; unsigned long v4l_mem_handle; + + u32 sar_width; + u32 sar_height; } /*vframe_t */; int get_curren_frame_para(int *top, int *left, int *bottom, int *right); diff --git a/include/linux/amlogic/media/vfm/vframe_provider.h b/include/linux/amlogic/media/vfm/vframe_provider.h index bfced60..e206215 100644 --- a/include/linux/amlogic/media/vfm/vframe_provider.h +++ b/include/linux/amlogic/media/vfm/vframe_provider.h @@ -28,6 +28,7 @@ struct vframe_states { #define VFRAME_EVENT_RECEIVER_GET_AUX_DATA 0x80 #define VFRAME_EVENT_RECEIVER_DISP_MODE 0x100 #define VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL 0x200 +#define VFRAME_EVENT_RECEIVER_NEED_NO_COMP 0x400 /* for VFRAME_EVENT_RECEIVER_GET_AUX_DATA*/ struct provider_aux_req_s { diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 9d14b7e..91e1622 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -82,56 +82,56 @@ enum { #define VPP_VD2_ALPHA_WID 9 #define VPP_VD2_ALPHA_MASK 0x1ff #define VPP_VD2_ALPHA_BIT 18 -#define VPP_OSD2_PREBLEND (1 << 17) -#define VPP_OSD1_PREBLEND (1 << 16) -#define VPP_VD2_PREBLEND (1 << 15) -#define VPP_VD1_PREBLEND (1 << 14) -#define VPP_OSD2_POSTBLEND (1 << 13) -#define VPP_OSD1_POSTBLEND (1 << 12) -#define VPP_VD2_POSTBLEND (1 << 11) -#define VPP_VD1_POSTBLEND (1 << 10) -#define VPP_OSD1_ALPHA (1 << 9) -#define VPP_OSD2_ALPHA (1 << 8) -#define VPP_POSTBLEND_EN (1 << 7) -#define VPP_PREBLEND_EN (1 << 6) -#define VPP_PRE_FG_SEL_MASK (1 << 5) -#define VPP_PRE_FG_OSD2 (1 << 5) +#define VPP_OSD2_PREBLEND BIT(17) +#define VPP_OSD1_PREBLEND BIT(16) +#define VPP_VD2_PREBLEND BIT(15) +#define VPP_VD1_PREBLEND BIT(14) +#define VPP_OSD2_POSTBLEND BIT(13) +#define VPP_OSD1_POSTBLEND BIT(12) +#define VPP_VD2_POSTBLEND BIT(11) +#define VPP_VD1_POSTBLEND BIT(10) +#define VPP_OSD1_ALPHA BIT(9) +#define VPP_OSD2_ALPHA BIT(8) +#define VPP_POSTBLEND_EN BIT(7) +#define VPP_PREBLEND_EN BIT(6) +#define VPP_PRE_FG_SEL_MASK BIT(5) +#define VPP_PRE_FG_OSD2 BIT(5) #define VPP_PRE_FG_OSD1 (0 << 5) -#define VPP_POST_FG_SEL_MASK (1 << 4) -#define VPP_POST_FG_OSD2 (1 << 4) +#define VPP_POST_FG_SEL_MASK BIT(4) +#define VPP_POST_FG_OSD2 BIT(4) #define VPP_POST_FG_OSD1 (0 << 4) -#define DNLP_SR1_CM (1 << 3) +#define DNLP_SR1_CM BIT(3) #define SR1_AFTER_POSTBLEN (0 << 3) -#define VPP_FIFO_RESET_DE (1 << 2) -#define PREBLD_SR0_VD1_SCALER (1 << 1) +#define VPP_FIFO_RESET_DE BIT(2) +#define PREBLD_SR0_VD1_SCALER BIT(1) #define SR0_AFTER_DNLP (0 << 1) -#define VPP_OUT_SATURATE (1 << 0) +#define VPP_OUT_SATURATE BIT(0) -#define VDIF_RESET_ON_GO_FIELD (1<<29) +#define VDIF_RESET_ON_GO_FIELD BIT(29) #define VDIF_URGENT_BIT 27 -#define VDIF_CHROMA_END_AT_LAST_LINE (1<<26) -#define VDIF_LUMA_END_AT_LAST_LINE (1<<25) +#define VDIF_CHROMA_END_AT_LAST_LINE BIT(26) +#define VDIF_LUMA_END_AT_LAST_LINE BIT(25) #define VDIF_HOLD_LINES_BIT 19 #define VDIF_HOLD_LINES_MASK 0x3f -#define VDIF_LAST_LINE (1<<18) -#define VDIF_BUSY (1<<17) -#define VDIF_DEMUX_MODE (1<<16) +#define VDIF_LAST_LINE BIT(18) +#define VDIF_BUSY BIT(17) +#define VDIF_DEMUX_MODE BIT(16) #define VDIF_DEMUX_MODE_422 (0<<16) -#define VDIF_DEMUX_MODE_RGB_444 (1<<16) +#define VDIF_DEMUX_MODE_RGB_444 BIT(16) #define VDIF_FORMAT_BIT 14 #define VDIF_FORMAT_MASK 3 #define VDIF_FORMAT_SPLIT (0<<14) -#define VDIF_FORMAT_422 (1<<14) +#define VDIF_FORMAT_422 BIT(14) #define VDIF_FORMAT_RGB888_YUV444 (2<<14) #define VDIF_BURSTSIZE_MASK 3 #define VDIF_BURSTSIZE_CR_BIT 12 #define VDIF_BURSTSIZE_CB_BIT 10 #define VDIF_BURSTSIZE_Y_BIT 8 -#define VDIF_MANULE_START_FRAME (1<<7) -#define VDIF_CHRO_RPT_LAST (1<<6) -#define VDIF_CHROMA_HZ_AVG (1<<3) -#define VDIF_LUMA_HZ_AVG (1<<2) -#define VDIF_SEPARATE_EN (1<<1) +#define VDIF_MANULE_START_FRAME BIT(7) +#define VDIF_CHRO_RPT_LAST BIT(6) +#define VDIF_CHROMA_HZ_AVG BIT(3) +#define VDIF_LUMA_HZ_AVG BIT(2) +#define VDIF_SEPARATE_EN BIT(1) #define VDIF_ENABLE (1<<0) #define VDIF_LOOP_MASK 0xff @@ -140,32 +140,32 @@ enum { #define VDIF_CHROMA_LOOP0_BIT 8 #define VDIF_LUMA_LOOP0_BIT 0 -#define HFORMATTER_REPEAT (1<<28) +#define HFORMATTER_REPEAT BIT(28) #define HFORMATTER_BILINEAR (0<<28) #define HFORMATTER_PHASE_MASK 0xf #define HFORMATTER_PHASE_BIT 24 -#define HFORMATTER_RRT_PIXEL0 (1<<23) +#define HFORMATTER_RRT_PIXEL0 BIT(23) #define HFORMATTER_YC_RATIO_1_1 (0<<21) -#define HFORMATTER_YC_RATIO_2_1 (1<<21) +#define HFORMATTER_YC_RATIO_2_1 BIT(21) #define HFORMATTER_YC_RATIO_4_1 (2<<21) -#define HFORMATTER_EN (1<<20) -#define VFORMATTER_ALWAYS_RPT (1<<19) -#define VFORMATTER_LUMA_RPTLINE0_DE (1<<18) -#define VFORMATTER_CHROMA_RPTLINE0_DE (1<<17) -#define VFORMATTER_RPTLINE0_EN (1<<16) +#define HFORMATTER_EN BIT(20) +#define VFORMATTER_ALWAYS_RPT BIT(19) +#define VFORMATTER_LUMA_RPTLINE0_DE BIT(18) +#define VFORMATTER_CHROMA_RPTLINE0_DE BIT(17) +#define VFORMATTER_RPTLINE0_EN BIT(16) #define VFORMATTER_SKIPLINE_NUM_MASK 0xf #define VFORMATTER_SKIPLINE_NUM_BIT 12 #define VFORMATTER_INIPHASE_MASK 0xf #define VFORMATTER_INIPHASE_BIT 8 #define VFORMATTER_PHASE_MASK (0x7f) #define VFORMATTER_PHASE_BIT 1 -#define VFORMATTER_EN (1<<0) +#define VFORMATTER_EN BIT(0) -#define VPP_PHASECTL_DOUBLE_LINE (1<<17) -#define VPP_PHASECTL_TYPE (1<<16) -#define VPP_PHASECTL_TYPE_PROG (0<<16) -#define VPP_PHASECTL_TYPE_INTERLACE (1<<16) -#define VPP_PHASECTL_VSL0B (1<<15) +#define VPP_PHASECTL_DOUBLE_LINE BIT(17) +#define VPP_PHASECTL_TYPE BIT(16) +#define VPP_PHASECTL_TYPE_PROG BIT(16) +#define VPP_PHASECTL_TYPE_INTERLACE BIT(16) +#define VPP_PHASECTL_VSL0B BIT(15) #define VPP_PHASECTL_DOUBLELINE_BIT 17 #define VPP_PHASECTL_DOUBLELINE_WID 2 #define VPP_PHASECTL_INIRPTNUM_MASK 0x3 @@ -174,27 +174,27 @@ enum { #define VPP_PHASECTL_INIRCVNUM_MASK 0xf #define VPP_PHASECTL_INIRCVNUM_WID 5 #define VPP_PHASECTL_INIRCVNUMB_BIT 8 -#define VPP_PHASECTL_VSL0T (1<<7) +#define VPP_PHASECTL_VSL0T BIT(7) #define VPP_PHASECTL_INIRPTNUMT_BIT 5 #define VPP_PHASECTL_INIRCVNUMT_BIT 0 #define VPP_LINE_BUFFER_EN_BIT 21 #define VPP_SC_PREHORZ_EN_BIT 20 #define VPP_SC_PREVERT_EN_BIT 19 -#define VPP_LINE_BUFFER_EN (1 << 21) -#define VPP_SC_PREHORZ_EN (1 << 20) -#define VPP_SC_PREVERT_EN (1 << 19) -#define VPP_SC_VERT_EN (1 << 18) -#define VPP_SC_HORZ_EN (1 << 17) -#define VPP_SC_TOP_EN (1 << 16) -#define VPP_SC_V1OUT_EN (1 << 15) -#define VPP_SC_RGN14_HNOLINEAR (1 << 12) +#define VPP_LINE_BUFFER_EN BIT(21) +#define VPP_SC_PREHORZ_EN BIT(20) +#define VPP_SC_PREVERT_EN BIT(19) +#define VPP_SC_VERT_EN BIT(18) +#define VPP_SC_HORZ_EN BIT(17) +#define VPP_SC_TOP_EN BIT(16) +#define VPP_SC_V1OUT_EN BIT(15) +#define VPP_SC_RGN14_HNOLINEAR BIT(12) #define VPP_SC_TOP_EN_WID 1 #define VPP_SC_TOP_EN_BIT 16 #define VPP_SC_BANK_LENGTH_WID 3 #define VPP_SC_BANK_LENGTH_MASK 0x7 #define VPP_SC_HBANK_LENGTH_BIT 8 -#define VPP_SC_RGN14_VNOLINEAR (1 << 4) +#define VPP_SC_RGN14_VNOLINEAR BIT(4) #define VPP_SC_VBANK_LENGTH_BIT 0 #define VPP_HSC_INIRPT_NUM_MASK 0x3 @@ -206,26 +206,26 @@ enum { #define VPP_OFIFO_LINELEN_MASK 0xfff #define VPP_OFIFO_LINELEN_BIT 20 -#define VPP_INV_VS (1 << 19) -#define VPP_INV_HS (1 << 18) -#define VPP_FORCE_FIELD_EN (1 << 17) -#define VPP_FORCE_FIELD_TYPE_MASK (1 << 16) +#define VPP_INV_VS BIT(19) +#define VPP_INV_HS BIT(18) +#define VPP_FORCE_FIELD_EN BIT(17) +#define VPP_FORCE_FIELD_TYPE_MASK BIT(16) #define VPP_FORCE_FIELD_TOP (0 << 16) -#define VPP_FORCE_FIELD_BOTTOM (1 << 16) -#define VPP_FOURCE_GO_FIELD (1 << 15) -#define VPP_FOURCE_GO_LINE (1 << 14) +#define VPP_FORCE_FIELD_BOTTOM BIT(16) +#define VPP_FOURCE_GO_FIELD BIT(15) +#define VPP_FOURCE_GO_LINE BIT(14) #define VPP_OFIFO_SIZE_WID 13 #define VPP_OFIFO_SIZE_MASK 0xfff #define VPP_OFIFO_SIZE_BIT 0 -#define VPP_COEF_IDXINC (1 << 15) -#define VPP_COEF_RD_CBUS (1 << 14) -#define VPP_COEF_SEP_EN (1 << 13) -#define VPP_COEF_9BIT (1 << 9) -#define VPP_COEF_TYPE (1 << 8) +#define VPP_COEF_IDXINC BIT(15) +#define VPP_COEF_RD_CBUS BIT(14) +#define VPP_COEF_SEP_EN BIT(13) +#define VPP_COEF_9BIT BIT(9) +#define VPP_COEF_TYPE BIT(8) #define VPP_COEF_VERT (0 << 8) -#define VPP_COEF_VERT_CHROMA (1 << 7) -#define VPP_COEF_HORZ (1 << 8) +#define VPP_COEF_VERT_CHROMA BIT(7) +#define VPP_COEF_HORZ BIT(8) #define VPP_COEF_INDEX_MASK 0x7f #define VPP_COEF_INDEX_BIT 0 diff --git a/include/linux/amlogic/media/vpu/vpu.h b/include/linux/amlogic/media/vpu/vpu.h index 1e57dea..9037103 100644 --- a/include/linux/amlogic/media/vpu/vpu.h +++ b/include/linux/amlogic/media/vpu/vpu.h @@ -96,6 +96,9 @@ struct vpu_dev_s { unsigned char clk_gate_state; }; +#define VPU_MEM_POWER_ON 0 +#define VPU_MEM_POWER_DOWN 1 + struct vpu_dev_s *vpu_dev_get(unsigned int vmod, char *owner_name); struct vpu_dev_s *vpu_dev_register(unsigned int vmod, char *owner_name); int vpu_dev_unregister(struct vpu_dev_s *vpu_dev); @@ -121,5 +124,7 @@ unsigned int vpu_vcbus_getb(unsigned int _reg, unsigned int _start, unsigned int _len); void vpu_vcbus_set_mask(unsigned int _reg, unsigned int _mask); void vpu_vcbus_clr_mask(unsigned int _reg, unsigned int _mask); - +int vpu_vmod_clk_request(unsigned int vclk, unsigned int vmod); +int vpu_vmod_clk_release(unsigned int vmod); +void vpu_vmod_mem_pd_switch(unsigned int vmod, int flag); #endif |