summaryrefslogtreecommitdiff
authorJian 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)
commitb58fe13d0eb92c25af49131299de9e3a796dc97e (patch)
tree1f28fb8bfa3da895dce098a536fb2e234e251b21
parent41de7c30dfe3df6fcfe6b08568a628174afaf6a9 (diff)
downloadcommon-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>
Diffstat
-rw-r--r--arch/arm/boot/dts/amlogic/meson-g12a.dtsi8
-rw-r--r--arch/arm/boot/dts/amlogic/meson-sm1.dtsi8
-rw-r--r--arch/arm/configs/meson64_a32_defconfig1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a.dtsi8
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1.dtsi8
-rw-r--r--arch/arm64/configs/meson64_a64_defconfig1
-rw-r--r--drivers/amlogic/media/Kconfig1
-rw-r--r--drivers/amlogic/media/Makefile1
-rw-r--r--drivers/amlogic/media/common/vpu/vpu.c6
-rw-r--r--drivers/amlogic/media/frame_sync/timestamp.c6
-rw-r--r--drivers/amlogic/media/frame_sync/tsync.c22
-rw-r--r--drivers/amlogic/media/video_sink/Kconfig39
-rw-r--r--drivers/amlogic/media/video_sink/Makefile2
-rw-r--r--drivers/amlogic/media/video_sink/amvideocap_priv.h70
-rw-r--r--drivers/amlogic/media/video_sink/video.c13311
-rw-r--r--drivers/amlogic/media/video_sink/video_keeper.c1183
-rw-r--r--drivers/amlogic/media/video_sink/video_priv.h162
-rw-r--r--drivers/amlogic/media/video_sink/videolog.h34
-rw-r--r--drivers/amlogic/media/video_sink/vpp.c3216
-rw-r--r--include/linux/amlogic/media/frame_sync/tsync.h2
-rw-r--r--include/linux/amlogic/media/registers/cpu_version.h51
-rw-r--r--include/linux/amlogic/media/registers/regs/vpp_regs.h3
-rw-r--r--include/linux/amlogic/media/vfm/vframe.h5
-rw-r--r--include/linux/amlogic/media/vfm/vframe_provider.h1
-rw-r--r--include/linux/amlogic/media/video_sink/video.h142
-rw-r--r--include/linux/amlogic/media/vpu/vpu.h7
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(&params, " ");
+ 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