blob: 6b7eb36962b15b11b7c4134df4e114a402bd2c81 [file] [log] [blame]
// 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/of.h>
#include <linux/of_fdt.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/amlogic/media/video_sink/video_signal_notify.h>
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
#include <linux/amlogic/media/vfm/vfm_ext.h>
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/clk.h>
#include <linux/debugfs.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/amlogic/media/video_sink/video_keeper.h>
#include "video_priv.h"
#include "video_reg.h"
#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO
#include <trace/events/meson_atrace.h>
#ifdef CONFIG_AMLOGIC_MEDIA_FRAME_SYNC
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/frame_sync/timestamp.h>
#include <linux/amlogic/media/frame_sync/tsync.h>
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
#include "vpp_pq.h"
#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"
#include "video_reg.h"
#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE
#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>
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN
#include "linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h"
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
#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"
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
#include <linux/amlogic/media/di/di.h>
#endif
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
#include <linux/amlogic/pm.h>
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_SECURITY
#include <linux/amlogic/media/vpu_secure/vpu_secure.h>
#endif
#include <linux/math64.h>
#include "video_receiver.h"
#include "video_multi_vsync.h"
#include <linux/amlogic/gki_module.h>
#define CREATE_TRACE_POINTS
#include "video_trace.h"
#undef TRACE_INCLUDE_PATH
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_PATH ../../drivers/amlogic/media/video_sink
#define TRACE_INCLUDE_FILE video_trace
#include <trace/define_trace.h>
#ifdef CONFIG_AMLOGIC_MEDIA_MSYNC
#include <uapi/linux/amlogic/msync.h>
#endif
static int get_count;
static int get_di_count;
static int put_di_count;
static int di_release_count;
static int get_count_pip;
static int get_count_pip2;
#define DEBUG_TMP 0
u32 vd1_vd2_mux_dts;
u32 osd_vpp_misc;
u32 osd_vpp_misc_mask;
bool update_osd_vpp_misc;
bool update_osd_vpp1_bld_ctrl;
bool update_osd_vpp2_bld_ctrl;
u32 osd_vpp1_bld_ctrl;
u32 osd_vpp1_bld_ctrl_mask;
u32 osd_vpp2_bld_ctrl;
u32 osd_vpp2_bld_ctrl_mask;
u32 osd_vpp_bld_ctrl_update_mask;
u32 osd_preblend_en;
int video_vsync = -ENXIO;
int video_vsync_viu2 = -ENXIO;
int video_vsync_viu3 = -ENXIO;
int video_pre_vsync = -ENXIO;
module_param(osd_vpp1_bld_ctrl, uint, 0444);
MODULE_PARM_DESC(osd_vpp1_bld_ctrl, "osd_vpp1_bld_ctrl");
module_param(osd_vpp2_bld_ctrl, uint, 0444);
MODULE_PARM_DESC(osd_vpp2_bld_ctrl, "osd_vpp2_bld_ctrl");
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
unsigned int det_stb_cnt = 30;
unsigned int det_unstb_cnt = 20;
unsigned int tolrnc_cnt = 6;
unsigned int timer_filter_en;
unsigned int aipq_set_policy;
unsigned int color_th = 100;
u32 get_stb_cnt(void)
{
return det_stb_cnt;
}
u32 get_unstb_cnt(void)
{
return det_unstb_cnt;
}
u32 get_tolrnc_cnt(void)
{
return tolrnc_cnt;
}
u32 get_timer_filter_en(void)
{
return timer_filter_en;
}
u32 get_aipq_set_policy(void)
{
return aipq_set_policy;
}
u32 get_color_th(void)
{
return color_th;
}
#endif
static struct ai_scenes_pq vpp_scenes[AI_SCENES_MAX];
static u32 cur_omx_index;
struct video_frame_detect_s {
u32 interrupt_count;
u32 start_receive_count;
};
static int tvin_delay_mode;
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;
static u32 omx_continusdrop_cnt;
#define OMX_PTS_DV_DEFAULT_UPPER 2500
#define OMX_PTS_DV_DEFAULT_LOWER -1600
static int omx_pts_interval_upper = 5500;
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 int omx_pts_set_from_hwc_count_begin;
static bool omx_check_previous_session;
u32 omx_cur_session = 0xffffffff;
static int drop_frame_count;
#define OMX_MAX_COUNT_RESET_SYSTEMTIME 2
#define OMX_MAX_COUNT_RESET_SYSTEMTIME_BEGIN 10
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 int hold_property_changed;
static struct video_frame_detect_s video_frame_detect;
static long long time_setomxpts;
static long long time_setomxpts_last;
struct nn_value_t nn_scenes_value[AI_PQ_TOP];
/*----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
bool bypass_pps = true;
/* for bit depth setting. */
int bit_depth_flag = 8;
bool omx_secret_mode;
static int omx_continuous_drop_count;
static bool omx_continuous_drop_flag;
static u32 cur_disp_omx_index;
#define OMX_CONTINUOUS_DROP_LEVEL 5
#define DEBUG_FLAG_FFPLAY BIT(0)
#define DEBUG_FLAG_CALC_PTS_INC BIT(1)
static bool dovi_drop_flag;
static int dovi_drop_frame_num;
#define RECEIVER_NAME "amvideo"
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static char dv_provider[32] = "dvbldec";
#endif
static s32 amvideo_poll_major;
/*static s8 dolby_first_delay;*/ /* for bug 145902 */
#define PARSE_MD_IN_ADVANCE 1
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;
#define RECEIVERPIP_NAME "videopip"
#define RECEIVERPIP2_NAME "videopip2"
static int pip_receiver_event_fun(int type, void *data, void *);
static int pip2_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 const struct vframe_receiver_op_s videopip2_vf_receiver = {
.event_cb = pip2_receiver_event_fun
};
static struct vframe_receiver_s videopip_vf_recv;
static struct vframe_receiver_s videopip2_vf_recv;
struct vpp_frame_par_s *curpip_frame_par;
struct vpp_frame_par_s *curpip2_frame_par;
struct vframe_s *cur_pipbuf;
struct vframe_s *cur_pipbuf2;
struct vframe_s local_pip;
struct vframe_s local_pip_ext;
struct vframe_s local_pip2;
struct vframe_s local_pip2_ext;
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;
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;
static u32 blend_conflict_cnt;
#ifdef FIQ_VSYNC
#define BRIDGE_IRQ INT_TIMER_C
#define BRIDGE_IRQ_SET() WRITE_CBUS_REG(ISA_TIMERC, 1)
#endif
/*********************************************************/
static DEFINE_MUTEX(video_layer_mutex);
static u32 layer_cap;
/* default value 20 30 */
static s32 black_threshold_width = 20;
static s32 black_threshold_height = 48;
static struct vframe_s hist_test_vf;
static bool hist_test_flag;
static unsigned long hist_buffer_addr;
static u32 hist_print_count;
atomic_t gafbc_request = ATOMIC_INIT(0);
/* #define DUR2PTS(x) ((x) - ((x) >> 4)) */
static inline int DUR2PTS(int x)
{
int var = x;
var -= var >> 4;
return var;
}
#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;
struct video_recv_s *gvideo_recv[3] = {NULL, NULL, NULL};
struct video_recv_s *gvideo_recv_vpp[2] = {NULL, NULL};
/*seek values on.video_define.h*/
int debug_flag;
int get_video_debug_flags(void)
{
return debug_flag;
}
static int vsync_enter_line_max;
static int vsync_exit_line_max;
static bool over_sync;
/* static int over_sync_count; */
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
static int vsync_rdma_line_max;
#endif
u32 framepacking_support;
static unsigned int framepacking_width = 1920;
static unsigned int framepacking_height = 2205;
unsigned int framepacking_blank = 45;
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 */
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, int, 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 videopip_get_vf_cnt;
static unsigned int videopip2_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);
static unsigned int videopip_drop_vf_cnt;
MODULE_PARM_DESC(videopip_drop_vf_cnt, "\n videopip_drop_vf_cnt\n");
module_param(videopip_drop_vf_cnt, uint, 0664);
static unsigned int videopip2_drop_vf_cnt;
MODULE_PARM_DESC(videopip2_drop_vf_cnt, "\n videopip2_drop_vf_cnt\n");
module_param(videopip2_drop_vf_cnt, uint, 0664);
static unsigned int disable_dv_drop;
MODULE_PARM_DESC(disable_dv_drop, "\n disable_dv_drop\n");
module_param(disable_dv_drop, uint, 0664);
static u32 vdin_frame_skip_cnt;
MODULE_PARM_DESC(vdin_frame_skip_cnt, "\n vdin_frame_skip_cnt\n");
module_param(vdin_frame_skip_cnt, uint, 0664);
static u32 vdin_err_crc_cnt;
MODULE_PARM_DESC(vdin_err_crc_cnt, "\n vdin_err_crc_cnt\n");
module_param(vdin_err_crc_cnt, uint, 0664);
#define ERR_CRC_COUNT 6
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static bool dv_mute_vpp_flag;
#endif
static unsigned int video_3d_format;
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN
static unsigned int mvc_flag;
#endif
unsigned int force_3d_scaler = 3;
static int last_mode_3d;
#endif
bool reverse;
u32 mirror;
bool vd1_vd2_mux;
bool aisr_en;
bool get_video_reverse(void)
{
return reverse;
}
EXPORT_SYMBOL(get_video_reverse);
bool is_di_hf_y_reverse(void)
{
//if (reverse || mirror == 2)
if (glayer_info[0].reverse || glayer_info[0].mirror == 2)
return cur_dev->di_hf_y_reverse;
else
return false;
}
EXPORT_SYMBOL(is_di_hf_y_reverse);
static const char video_dev_id[] = "amvideo-dev";
static u32 stop_update;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
static bool first_irq = true;
#endif
#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 */
#define AVSYNC_COUNT
#ifdef AVSYNC_COUNT
static bool av_discontinue;
static u32 avsync_count;
#endif
#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 DEFINE_SPINLOCK(hdmi_avsync_lock);
static u32 vpts_remainder;
static u32 video_notify_flag;
static int enable_video_discontinue_report = 1;
static struct amvideo_device_data_s amvideo_meson_dev;
bool video_suspend;
u32 video_suspend_cycle;
int log_out;
#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE
static struct amvideocap_req *capture_frame_req;
#endif
u32 get_video_angle(void)
{
return glayer_info[0].angle;
}
EXPORT_SYMBOL(get_video_angle);
void set_video_zorder(u32 zorder, u32 index)
{
if (index < 2)
glayer_info[index].zorder = zorder;
}
EXPORT_SYMBOL(set_video_zorder);
/*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)
{
vd_layer[0].property_changed = flag ? true : false;
return 0;
}
void get_video_axis_offset(s32 *x_offset, s32 *y_offset)
{
struct disp_info_s *layer = &glayer_info[0];
*x_offset = layer->layer_left;
*y_offset = layer->layer_top;
}
#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 = kstrtouint(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 void dump_mif_reg(void)
{
int i;
u32 reg_addr, reg_val = 0;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
pr_info("vd%d mif regs:\n", i);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_gen_reg;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_canvas0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_canvas1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma_x0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma_y0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma_x0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma_y0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma_x1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma_y1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma_x1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma_y1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_rpt_loop;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma0_rpt_pat;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma0_rpt_pat;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma1_rpt_pat;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma1_rpt_pat;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma_psel;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_chroma_psel;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_luma_fifo_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_gen_reg2;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.vd_if0_gen_reg3;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.viu_vd_fmt_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_reg.viu_vd_fmt_w;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
if (cur_dev->mif_linear) {
pr_info("vd%d mif linear regs:\n", i);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_baddr_y;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_baddr_cb;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_baddr_cr;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_stride_0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_stride_1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_baddr_y_f1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_baddr_cb_f1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_baddr_cr_f1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_stride_0_f1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_mif_linear_reg.vd_if0_stride_1_f1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
}
}
static void dump_afbc_reg(void)
{
int i;
u32 reg_addr, reg_val = 0;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
pr_info("vd%d afbc regs:\n", i);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_enable;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_mode;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_size_in;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_dec_def_color;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_conv_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_lbuf_depth;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_head_baddr;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_body_baddr;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_size_out;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_out_yscope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_vd_cfmt_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_vd_cfmt_w;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_mif_hor_scope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_mif_ver_scope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_pixel_hor_scope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_pixel_ver_scope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_vd_cfmt_h;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vd_afbc_reg.afbc_top_ctrl;
if (cur_dev->t7_display && reg_addr) {
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
}
}
static void dump_pps_reg(void)
{
int i;
u32 reg_addr, reg_val = 0;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
pr_info("vd%d pps regs:\n", i);
reg_addr = vd_layer[i].pps_reg.vd_vsc_region12_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_region34_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_region4_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_start_phase_step;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_region1_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_region3_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_phase_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_vsc_init_phase;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_region12_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_region34_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_region4_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_start_phase_step;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_region1_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_region3_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_phase_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_sc_misc;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_hsc_phase_ctrl1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_prehsc_coef;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_pre_scale_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].pps_reg.vd_prevsc_coef;
if (reg_addr) {
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
reg_addr = vd_layer[i].pps_reg.vd_prehsc_coef1;
if (reg_addr) {
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
}
}
static void dump_vpp_blend_reg(void)
{
int i;
u32 reg_addr, reg_val = 0;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
pr_info("vd%d pps blend regs:\n", i);
reg_addr = vd_layer[i].vpp_blend_reg.preblend_h_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("preblend_h_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vpp_blend_reg.preblend_v_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("preblend_v_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vpp_blend_reg.preblend_h_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("preblend_h_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vpp_blend_reg.postblend_h_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("postblend_h_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].vpp_blend_reg.postblend_v_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("postblend_v_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
}
static void dump_fgrain_reg(void)
{
int i;
u32 reg_addr, reg_val = 0;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
if (glayer_info[i].fgrain_support) {
pr_info("vd%d fgrain regs:\n", i);
reg_addr = vd_layer[i].fg_reg.fgrain_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].fg_reg.fgrain_win_h;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vd_layer[i].fg_reg.fgrain_win_v;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
}
}
static void dump_aisr_reg(void)
{
u32 reg_addr, reg_val = 0;
pr_info("aisr reshape regs:\n");
reg_addr = aisr_reshape_reg.aisr_reshape_ctrl0;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_ctrl1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_scope_x;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_scope_y;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr00;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr01;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr02;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr03;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr10;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr11;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr12;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr13;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr20;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr21;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr22;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr23;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr30;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr31;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr32;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_reshape_baddr33;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_post_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_post_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = aisr_reshape_reg.aisr_sr1_nn_post_top;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
pr_info("aisr pps regs:\n");
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_region12_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_region34_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_region4_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_start_phase_step;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_region1_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_region3_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_phase_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_vsc_init_phase;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_region12_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_region34_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_region4_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_start_phase_step;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_region1_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_region3_phase_slope;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_phase_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_sc_misc;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_hsc_phase_ctrl1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_prehsc_coef;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_pre_scale_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = cur_dev->aisr_pps_reg.vd_prevsc_coef;
if (reg_addr) {
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
reg_addr = cur_dev->aisr_pps_reg.vd_prehsc_coef1;
if (reg_addr) {
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
}
static void dump_vpp_path_size_reg(void)
{
u32 reg_addr, reg_val = 0;
if (!cur_dev->t7_display)
return;
pr_info("vpp path size reg:\n");
reg_addr = vpp_path_size_reg.vd1_hdr_in_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd1_hdr_in_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd2_hdr_in_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd2_hdr_in_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd3_hdr_in_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd3_hdr_in_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vpp_line_in_length;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_line_in_length[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vpp_pic_in_height;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_pic_in_height[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd1_sc_h_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd1_sc_h_startp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd1_sc_h_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd1_sc_h_endp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd1_sc_v_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd1_sc_v_startp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd1_sc_v_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd1_sc_v_endp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd2_sc_h_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd2_sc_h_startp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd2_sc_h_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd2_sc_h_endp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd2_sc_v_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd2_sc_v_startp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd2_sc_v_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd2_sc_v_endp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd3_sc_h_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd3_sc_h_startp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd3_sc_h_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd3_sc_h_endp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd3_sc_v_startp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd3_sc_v_startp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vd3_sc_v_endp;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd3_sc_v_endp[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vpp_preblend_h_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_preblend_h_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.preblend_vd1_h_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("preblend_vd1_h_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.preblend_vd1_v_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("preblend_vd1_v_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vpp_ve_h_v_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_ve_h_v_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vpp_postblend_h_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_postblend_h_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.vpp_out_h_v_size;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_out_h_v_size[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.postblend_vd1_h_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("postblend_vd1_h_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.postlend_vd1_v_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("postlend_vd1_v_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.blend_vd2_h_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("blend_vd2_h_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.blend_vd2_v_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("blend_vd2_v_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.blend_vd3_h_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("blend_vd3_h_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = vpp_path_size_reg.blend_vd3_v_start_end;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("blend_vd3_v_start_end[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
static void dump_vpp_misc_reg(void)
{
u32 reg_addr, reg_val = 0;
if (!cur_dev->t7_display)
return;
pr_info("vpp misc reg:\n");
reg_addr = viu_misc_reg.mali_afbcd_top_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("mali_afbcd_top_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.mali_afbcd1_top_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("mali_afbcd1_top_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.mali_afbcd2_top_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("mali_afbcd2_top_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.vpp_vd1_top_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_vd1_top_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.vpp_vd2_top_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_vd2_top_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.vpp_vd3_top_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_vd3_top_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.vd_path_misc_ctrl;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vd_path_misc_ctrl[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.path_start_sel;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("path_start_sel[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.vpp_misc;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_misc[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = viu_misc_reg.vpp_misc1;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("vpp_misc1[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
static void dump_zorder_reg(void)
{
u32 reg_addr, reg_val = 0;
if (!cur_dev->t7_display)
return;
pr_info("vpp zorder reg:\n");
reg_addr = VD1_BLEND_SRC_CTRL;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("VD1_BLEND_SRC_CTRL[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = VD2_BLEND_SRC_CTRL;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("VD2_BLEND_SRC_CTRL[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = VD3_BLEND_SRC_CTRL;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("VD3_BLEND_SRC_CTRL[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = OSD1_BLEND_SRC_CTRL;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("OSD1_BLEND_SRC_CTRL[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr = OSD2_BLEND_SRC_CTRL;
reg_val = READ_VCBUS_REG(reg_addr);
pr_info("OSD2_BLEND_SRC_CTRL[0x%x] = 0x%X\n",
reg_addr, reg_val);
}
static ssize_t dump_reg_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return count;
}
static int dump_reg_show(struct seq_file *s, void *what)
{
unsigned int i = 0, count;
u32 reg_addr, reg_val = 0;
struct sr_info_s *sr;
/* viu top regs */
seq_puts(s, "\nviu top registers:\n");
reg_addr = 0x1a04;
count = 12;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
/* vpp registers begin from 0x1d00*/
seq_puts(s, "vpp registers:\n");
reg_addr = VPP_DUMMY_DATA + cur_dev->vpp_off;
count = 256;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
/* vd1 afbc regs */
seq_puts(s, "\nvd1 afbc registers:\n");
reg_addr = vd_layer[0].vd_afbc_reg.afbc_enable;
count = 32;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
/* vd2 afbc regs */
seq_puts(s, "\nvd2 afbc registers:\n");
reg_addr = vd_layer[1].vd_afbc_reg.afbc_enable;
count = 32;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
if (cur_dev->max_vd_layers == 3) {
/* vd3 afbc regs */
seq_puts(s, "\nvd3 afbc registers:\n");
reg_addr = vd_layer[2].vd_afbc_reg.afbc_enable;
count = 32;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
}
/* vd1 mif */
seq_puts(s, "\nvd1 mif registers:\n");
reg_addr = vd_layer[0].vd_mif_reg.vd_if0_gen_reg;
count = 32;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
/* vd2 mif */
seq_puts(s, "\nvd2 mif registers:\n");
reg_addr = vd_layer[1].vd_mif_reg.vd_if0_gen_reg;
count = 32;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
if (cur_dev->max_vd_layers == 3) {
/* vd3 mif */
seq_puts(s, "\nvd3 mif registers:\n");
reg_addr = vd_layer[2].vd_mif_reg.vd_if0_gen_reg;
count = 32;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
}
/* vd1(0x3800) & vd2(0x3850) hdr */
/* osd hdr (0x38a0) */
seq_puts(s, "\nvd1(0x3800) & vd2(0x3850) hdr registers:\n");
seq_puts(s, "osd hdr (0x38a0) registers:\n");
reg_addr = 0x3800;
count = 256;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
/* super scaler */
sr = &sr_info;
/* g12a ~ tm2: 0x3e00 */
/* tm2 revb: 0x5000 */
seq_puts(s, "\nsuper scaler 0 registers:\n");
reg_addr = SRSHARP0_SHARP_HVSIZE + sr->sr_reg_offt;
count = 128;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
/* tl1, tm2 : 0x3f00*/
/* tm2 revb: 0x5200 */
seq_puts(s, "\nsuper scaler 1 registers:\n");
reg_addr = SRSHARP1_SHARP_HVSIZE + sr->sr_reg_offt2;
count = 128;
for (i = 0; i < count; i++) {
reg_val = READ_VCBUS_REG(reg_addr);
seq_printf(s, "[0x%x] = 0x%X\n",
reg_addr, reg_val);
reg_addr += 1;
}
return 0;
}
static int dump_reg_open(struct inode *inode, struct file *file)
{
return single_open(file, dump_reg_show, inode->i_private);
}
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
static const struct file_operations reg_dump_file_ops = {
.open = dump_reg_open,
.read = seq_read,
.write = dump_reg_write,
.release = single_release,
};
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
{"reg_dump", S_IFREG | 0644,
&reg_dump_file_ops
},
};
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");
return;
}
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);
}
bool to_notify_trick_wait;
/* display canvas */
#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;
static struct vframe_s *pip_rdma_buf;
static struct vframe_s *pip2_rdma_buf;
static struct vframe_s *pipbuf_to_put[DISPBUF_TO_PUT_MAX];
static s8 pipbuf_to_put_num;
static struct vframe_s *pipbuf2_to_put[DISPBUF_TO_PUT_MAX];
static s8 pipbuf2_to_put_num;
static struct vframe_s *dispbuf_to_put[DISPBUF_TO_PUT_MAX];
static s8 dispbuf_to_put_num;
#endif
/* 0: amvideo, 1: pip */
/* rdma buf + dispbuf + to_put_buf */
static struct vframe_s *recycle_buf[MAX_VD_LAYERS][1 + DISPBUF_TO_PUT_MAX];
static s32 recycle_cnt[MAX_VD_LAYERS];
static u32 post_canvas;
static u32 blackout;
u32 force_blackout;
static u32 blackout_pip;
static u32 blackout_pip2;
/* disable video */
static u32 pip_frame_count;
static u32 pip2_frame_count;
static u32 pip_loop;
static u32 pip2_loop;
static u32 hold_video;
/* 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 */
const struct vinfo_s *vinfo;
/* config */
struct vframe_s *cur_dispbuf;
static struct vframe_s *cur_dispbuf2;
//static struct vframe_s *cur_dispbuf3;
bool need_disable_vd2;
bool need_disable_vd3;
static bool last_mvc_status;
struct vframe_s vf_local, vf_local2, vf_local_ext;
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;
/* 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_prop_change = ATOMIC_INIT(0);
atomic_t status_changed = ATOMIC_INIT(0);
atomic_t axis_changed = ATOMIC_INIT(0);
atomic_t video_unreg_flag = ATOMIC_INIT(0);
atomic_t vt_unreg_flag = ATOMIC_INIT(0);
atomic_t vt_disable_video_done = 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);
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
static u32 dmc_config_state;
static u32 last_toggle_count;
static u32 toggle_same_count;
#endif
static int hdmin_delay_start;
static int hdmin_delay_start_time;
static int hdmin_delay_duration;
static int hdmin_delay_min_ms;
static int hdmin_delay_max_ms = 128;
static int hdmin_delay_done = true;
static int hdmin_need_drop_count;
static int vframe_walk_delay;
static int last_required_total_delay;
static int hdmi_vframe_count;
static bool hdmi_delay_first_check;
static u8 hdmi_delay_normal_check; /* 0xff: always check, n: check n times */
static u32 hdmin_delay_count_debug;
/* 0xff: always check, n: check n times after first check */
static u8 enable_hdmi_delay_normal_check = 1;
#define HDMI_DELAY_FIRST_CHECK_COUNT 60
#define HDMI_DELAY_NORMAL_CHECK_COUNT 300
#define HDMI_VIDEO_MIN_DELAY 3
/* video_inuse */
u32 video_inuse;
u32 get_playback_delay_duration(void)
{
u32 memc_delay = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_FRC
memc_delay = frc_get_video_latency();
#endif
return memc_delay;
}
EXPORT_SYMBOL(get_playback_delay_duration);
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);
u32 get_first_pic_coming(void)
{
return first_frame_toggled;
}
EXPORT_SYMBOL(get_first_pic_coming);
u32 get_toggle_frame_count(void)
{
return new_frame_count;
}
EXPORT_SYMBOL(get_toggle_frame_count);
void set_video_peek(void)
{
videopeek = true;
}
EXPORT_SYMBOL(set_video_peek);
u32 get_first_frame_toggled(void)
{
return first_frame_toggled;
}
EXPORT_SYMBOL(get_first_frame_toggled);
/* wait queue for poll */
static wait_queue_head_t amvideo_trick_wait;
/* wait queue for poll */
static wait_queue_head_t amvideo_prop_change_wait;
static u32 vpts_ref;
static u32 video_frame_repeat_count;
static u32 smooth_sync_enable;
static u32 hdmi_in_onvideo;
/* vpp_crc */
static u32 vpp_crc_en;
static int vpp_crc_result;
/* viu2 vpp_crc */
static u32 vpp_crc_viu2_en;
/* source fmt string */
const char *src_fmt_str[] = {
"SDR", "HDR10", "HDR10+", "HDR Prime", "HLG",
"Dolby Vison", "Dolby Vison Low latency", "MVC"
};
atomic_t primary_src_fmt =
ATOMIC_INIT(VFRAME_SIGNAL_FMT_INVALID);
atomic_t cur_primary_src_fmt =
ATOMIC_INIT(VFRAME_SIGNAL_FMT_INVALID);
u32 video_prop_status;
u32 video_info_change_status;
u32 force_switch_vf_mode;
#define CONFIG_AM_VOUT
static s32 is_afbc_for_vpp(u8 id)
{
s32 ret = -1;
u32 val;
if (id >= MAX_VD_LAYERS || legacy_vpp)
return ret;
/* karry */
if (cur_dev->t7_display)
return 0;
if (id == 0)
val = READ_VCBUS_REG(VD1_AFBCD0_MISC_CTRL);
else
val = READ_VCBUS_REG(VD2_AFBCD1_MISC_CTRL);
if ((val & (1 << 10)) && (val & (1 << 12)) &&
!(val & (1 << 9)))
ret = 1;
else
ret = 0;
return ret;
}
s32 di_request_afbc_hw(u8 id, bool on)
{
u32 cur_afbc_request;
u32 next_request = 0;
s32 ret = -1;
if (id >= MAX_VD_LAYERS)
return ret;
if (!glayer_info[id].afbc_support || legacy_vpp)
return ret;
next_request = 1 << id;
cur_afbc_request = atomic_read(&gafbc_request);
if (on) {
if (cur_afbc_request & next_request)
return is_afbc_for_vpp(id);
atomic_add(next_request, &gafbc_request);
ret = 1;
} else {
if ((cur_afbc_request & next_request) == 0)
return is_afbc_for_vpp(id);
atomic_sub(next_request, &gafbc_request);
ret = 1;
}
vd_layer[id].property_changed = true;
if (id > 0 && vd_layer[id].vpp_index != VPP0)
vd_layer_vpp[id - 1].property_changed = true;
return ret;
}
EXPORT_SYMBOL(di_request_afbc_hw);
/*********************************************************/
static inline struct vframe_s *pip2_vf_peek(void)
{
if (pip2_loop && cur_dispbuf != cur_pipbuf2)
return cur_dispbuf;
return vf_peek(RECEIVERPIP2_NAME);
}
static inline struct vframe_s *pip2_vf_get(void)
{
struct vframe_s *vf = NULL;
if (pip2_loop && cur_dispbuf != cur_pipbuf2)
return cur_dispbuf;
vf = vf_get(RECEIVERPIP2_NAME);
if (vf) {
get_count_pip2++;
if (vf->type & VIDTYPE_V4L_EOS) {
vf_put(vf, RECEIVERPIP2_NAME);
return NULL;
}
/* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */
atomic_set(&vf->use_cnt_pip, 1);
/* atomic_set(&vf->use_cnt_pip2, 1); */
}
return vf;
}
static inline int pip2_vf_put(struct vframe_s *vf)
{
struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP2_NAME);
if (pip2_loop)
return 0;
/* if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip2)) { */
if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip)) {
if (vf_put(vf, RECEIVERPIP2_NAME) < 0)
return -EFAULT;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if ((glayer_info[0].display_path_id
== VFM_PATH_PIP2) &&
is_dolby_vision_enable())
dolby_vision_vf_put(vf);
#endif
/* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */
} else {
if (vf)
return -EINVAL;
}
return 0;
}
static inline struct vframe_s *pip_vf_peek(void)
{
if (pip_loop && cur_dispbuf != cur_pipbuf)
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 && cur_dispbuf != cur_pipbuf)
return cur_dispbuf;
vf = vf_get(RECEIVERPIP_NAME);
if (vf) {
get_count_pip++;
if (vf->type & VIDTYPE_V4L_EOS) {
vf_put(vf, RECEIVERPIP_NAME);
return NULL;
}
/* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */
atomic_set(&vf->use_cnt_pip, 1);
}
return vf;
}
static inline int pip_vf_put(struct vframe_s *vf)
{
struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP_NAME);
if (pip_loop)
return 0;
if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip)) {
if (vf_put(vf, RECEIVERPIP_NAME) < 0)
return -EFAULT;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if ((glayer_info[0].display_path_id
== VFM_PATH_PIP) &&
is_dolby_vision_enable())
dolby_vision_vf_put(vf);
#endif
/* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */
} else {
if (vf)
return -EINVAL;
}
return 0;
}
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;
}
#ifdef used_fence
if (vf && vf->fence) {
int ret = 0;
/*
* the ret of fence status.
* 0: has not been signaled.
* 1: signaled without err.
* other: fence err.
*/
ret = fence_get_status(vf->fence);
if (ret < 0) {
vf = vf_get(RECEIVER_NAME);
if (vf)
vf_put(vf, RECEIVER_NAME);
} else if (ret == 0) {
vf = NULL;
}
}
#endif
return vf;
}
void pre_process_for_3d(struct vframe_s *vf)
{
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 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;
}
#endif
}
static inline struct vframe_s *video_vf_get(void)
{
struct vframe_s *vf = NULL;
if (hist_test_flag) {
if (cur_dispbuf != &hist_test_vf)
vf = &hist_test_vf;
return vf;
}
vf = vf_get(RECEIVER_NAME);
if (vf) {
get_count++;
if (vf->type & VIDTYPE_V4L_EOS) {
vf_put(vf, RECEIVER_NAME);
return NULL;
}
if (IS_DI_POSTWRTIE(vf->type))
get_di_count++;
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;
}
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;
}
pre_process_for_3d(vf);
receive_frame_count++;
}
return vf;
}
static int video_vf_get_states(struct vframe_states *states)
{
int ret;
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 int video_vf_put(struct vframe_s *vf)
{
struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME);
if (vf == &hist_test_vf)
return 0;
if (!vfp || !vf) {
if (!vf)
return 0;
return -EINVAL;
}
if (atomic_dec_and_test(&vf->use_cnt)) {
if (vf_put(vf, RECEIVER_NAME) < 0)
return -EFAULT;
if (IS_DI_POSTWRTIE(vf->type))
put_di_count++;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable())
dolby_vision_vf_put(vf);
#endif
video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT;
} else {
return -EINVAL;
}
return 0;
}
static bool check_dispbuf(struct vframe_s *vf, bool is_put_err)
{
int i;
bool done = false;
if (!vf)
return true;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (!is_put_err ||
(is_put_err && IS_DI_POSTWRTIE(vf->type))) {
if (!dispbuf_to_put[i]) {
dispbuf_to_put[i] = vf;
dispbuf_to_put_num++;
done = true;
break;
}
}
}
return done;
}
int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index)
{
if (!cur_dispbuf)
return -1;
atomic_inc(&cur_dispbuf->use_cnt);
*canvas_index = READ_VCBUS_REG(vd_layer[0].vd_mif_reg.vd_if0_canvas0);
*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;
memset(&states, 0, sizeof(struct vframe_states));
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_MEDIA_VIDEOCAPTURE
int ext_put_video_frame(struct vframe_s *vf)
{
if (vf == &vf_local)
return 0;
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
return 0;
}
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
#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
#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 bool check_pipbuf(struct vframe_s *vf, bool is_put_err)
{
int i;
bool done = false;
if (!vf)
return true;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (!is_put_err ||
(is_put_err && IS_DI_POSTWRTIE(vf->type))) {
if (!pipbuf_to_put[i]) {
pipbuf_to_put[i] = vf;
pipbuf_to_put_num++;
done = true;
break;
}
}
}
return done;
}
static struct vframe_s *pip_toggle_frame(struct vframe_s *vf)
{
u32 first_picture = 0;
if (!vf)
return NULL;
if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME)
pr_info("%s(%p)\n", __func__, vf);
if (vf->width == 0 || vf->height == 0) {
amlog_level(LOG_LEVEL_ERROR,
"Video: invalid frame dimension\n");
return vf;
}
if (cur_pipbuf && cur_pipbuf != &local_pip && cur_pipbuf != vf) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i = 0;
if (is_vsync_rdma_enable()) {
if (pip_rdma_buf == cur_pipbuf) {
if (!check_pipbuf(cur_pipbuf, false)) {
if (pip_vf_put(cur_pipbuf) < 0)
pr_info("put err, line: %d\n",
__LINE__);
}
} else {
if (pip_vf_put(cur_pipbuf) < 0) {
if (!check_pipbuf(cur_pipbuf, true))
pr_info("put err,pip full\n");
}
}
} else {
for (i = 0; i < pipbuf_to_put_num; i++) {
if (pipbuf_to_put[i]) {
if (!pip_vf_put(pipbuf_to_put[i])) {
pipbuf_to_put[i] = NULL;
pipbuf_to_put_num--;
}
}
}
if (pip_vf_put(cur_pipbuf) < 0)
check_pipbuf(cur_pipbuf, true);
}
#else
if (pip_vf_put(cur_pipbuf) < 0)
check_pipbuf(cur_pipbuf, true);
#endif
pip_frame_count++;
if (pip_frame_count == 1)
first_picture = 1;
} else if (!cur_pipbuf || (cur_pipbuf == &local_pip))
first_picture = 1;
if (cur_pipbuf != vf)
vf->type_backup = vf->type;
if (first_picture && (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME))
pr_info("%s(%p)\n", __func__, vf);
cur_pipbuf = vf;
return cur_pipbuf;
}
static bool check_pipbuf2(struct vframe_s *vf, bool is_put_err)
{
int i;
bool done = false;
if (!vf)
return true;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (!is_put_err ||
(is_put_err && IS_DI_POSTWRTIE(vf->type))) {
if (!pipbuf2_to_put[i]) {
pipbuf2_to_put[i] = vf;
pipbuf2_to_put_num++;
done = true;
break;
}
}
}
return done;
}
static struct vframe_s *pip2_toggle_frame(struct vframe_s *vf)
{
u32 first_picture = 0;
if (!vf)
return NULL;
if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME)
pr_info("%s(%p)\n", __func__, vf);
if (vf->width == 0 || vf->height == 0) {
amlog_level
(LOG_LEVEL_ERROR,
"Video: invalid frame dimension\n");
return vf;
}
if (cur_pipbuf2 && cur_pipbuf2 != &local_pip2 && cur_pipbuf2 != vf) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i = 0;
if (is_vsync_rdma_enable()) {
if (pip2_rdma_buf == cur_pipbuf2) {
if (!check_pipbuf2(cur_pipbuf2, false)) {
if (pip2_vf_put(cur_pipbuf2) < 0)
pr_info("put err, line: %d\n",
__LINE__);
}
} else {
if (pip2_vf_put(cur_pipbuf2) < 0) {
if (!check_pipbuf2(cur_pipbuf2, true))
pr_info("put err,pip2 full\n");
}
}
} else {
for (i = 0; i < pipbuf2_to_put_num; i++) {
if (pipbuf2_to_put[i]) {
if (!pip2_vf_put(pipbuf2_to_put[i])) {
pipbuf2_to_put[i] = NULL;
pipbuf2_to_put_num--;
}
}
}
if (pip2_vf_put(cur_pipbuf2) < 0)
check_pipbuf2(cur_pipbuf2, true);
}
#else
if (pip2_vf_put(cur_pipbuf2) < 0)
check_pipbuf2(cur_pipbuf2, true);
#endif
pip2_frame_count++;
if (pip2_frame_count == 1)
first_picture = 1;
} else if (!cur_pipbuf2 || (cur_pipbuf2 == &local_pip2))
first_picture = 1;
if (cur_pipbuf2 != vf)
vf->type_backup = vf->type;
if (first_picture && (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME))
pr_info("%s(%p)\n", __func__, vf);
cur_pipbuf2 = vf;
return cur_pipbuf2;
}
/* for sdr/hdr/single dv switch with dual dv */
u32 last_el_status;
bool has_enhanced_layer(struct vframe_s *vf)
{
struct provider_aux_req_s req;
enum vframe_signal_fmt_e fmt;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_el_disable() &&
!for_dolby_vision_certification())
return 0;
#endif
if (!vf)
return 0;
if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS)
return 0;
if (!is_dolby_vision_on())
return 0;
fmt = get_vframe_src_fmt(vf);
/* valid src_fmt = DOVI or invalid src_fmt will check dual layer */
/* otherwise, it certainly is a non-dv vframe */
if (fmt != VFRAME_SIGNAL_FMT_DOVI &&
fmt != VFRAME_SIGNAL_FMT_INVALID)
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;
}
static bool has_receive_dummy_vframe(void)
{
struct vframe_s *vf;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
vf = video_vf_peek();
if (vf && vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
/* get dummy vf. */
vf = video_vf_get();
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA /* recycle vframe. */
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (dispbuf_to_put[i]) {
if (!video_vf_put(dispbuf_to_put[i])) {
dispbuf_to_put[i] = NULL;
dispbuf_to_put_num--;
}
}
}
#endif
/* recycle the last vframe. */
if (cur_dispbuf && cur_dispbuf != &vf_local) {
if (!video_vf_put(cur_dispbuf))
cur_dispbuf = NULL;
}
/*pr_info("put dummy vframe.\n");*/
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
return true;
}
return false;
}
static u64 func_div(u64 number, u32 divid)
{
u64 tmp = number;
do_div(tmp, divid);
return tmp;
}
static void update_process_hdmi_avsync_flag(bool flag)
{
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
unsigned long flags;
/*enable hdmi delay process only when audio have required*/
if (last_required_total_delay <= 0)
return;
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name && (!strcmp(provider_name, "dv_vdin") ||
!strcmp(provider_name, "vdin0"))) {
spin_lock_irqsave(&hdmi_avsync_lock, flags);
hdmi_delay_first_check = flag;
hdmi_vframe_count = 0;
hdmin_delay_count_debug = 0;
if (enable_hdmi_delay_normal_check && flag)
hdmi_delay_normal_check = enable_hdmi_delay_normal_check;
else
hdmi_delay_normal_check = 0;
pr_info("update hdmi_delay_check %d\n", flag);
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
}
}
static inline bool is_valid_drop_count(int drop_count)
{
if (drop_count > 0 && drop_count < 8)
return true;
return false;
}
static void process_hdmi_video_sync(struct vframe_s *vf)
{
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
int update_value = 0;
unsigned long flags;
int vsync_dur = 16;
int need_drop = 0;
int hdmin_delay_min_ms = vsync_dur * HDMI_VIDEO_MIN_DELAY;
if ((!hdmi_delay_first_check && !hdmi_delay_normal_check &&
hdmin_delay_start == 0) || !vf || last_required_total_delay <= 0)
return;
hdmin_delay_duration = 0;
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name && (!strcmp(provider_name, "dv_vdin") ||
!strcmp(provider_name, "vdin0"))) {
if (vf->duration > 0) {
vsync_dur = (int)(vf->duration / 96);
hdmin_delay_min_ms = vsync_dur *
HDMI_VIDEO_MIN_DELAY;
}
spin_lock_irqsave(&hdmi_avsync_lock, flags);
if (last_required_total_delay > vframe_walk_delay) { /*delay video*/
vframe_walk_delay = (int)div_u64(((jiffies_64 -
vf->ready_jiffies64) * 1000), HZ);
/*check hdmi max delay*/
if (last_required_total_delay > hdmin_delay_max_ms) {
if (hdmin_delay_max_ms > vframe_walk_delay)
update_value = hdmin_delay_max_ms -
vframe_walk_delay;
} else {
update_value = last_required_total_delay -
vframe_walk_delay;
}
/*set only if delay bigger than half vsync*/
if (update_value > vsync_dur / 2) {
hdmin_delay_duration = update_value;
hdmin_delay_start_time = -1;
hdmin_delay_count_debug++;
hdmin_delay_done = false;
hdmin_need_drop_count = 0;
}
} else { /*drop video*/
/*check hdmi min delay*/
if (last_required_total_delay >= hdmin_delay_min_ms)
update_value = vframe_walk_delay -
last_required_total_delay;
else
update_value = vframe_walk_delay -
hdmin_delay_min_ms;
/*drop only if diff bigger than half vsync*/
if (update_value > vsync_dur / 2) {
need_drop = update_value / vsync_dur;
/*check if drop need_drop + 1 is closer to*/
/*required than need_drop*/
if ((update_value - need_drop * vsync_dur) >
vsync_dur / 2) {
if ((vframe_walk_delay -
(need_drop + 1) * vsync_dur) >=
hdmin_delay_min_ms)
need_drop = need_drop + 1;
}
hdmin_delay_duration = -update_value;
hdmin_delay_done = true;
if (is_valid_drop_count(need_drop))
hdmin_need_drop_count = need_drop;
}
}
//if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("required delay:%d, current %d, extra %d, delay %s, drop cnt %d, normal_check:0x%02x\n",
last_required_total_delay,
vframe_walk_delay,
hdmin_delay_duration,
hdmin_delay_done ? "false" : "true",
need_drop, hdmi_delay_normal_check);
/* retry n times after vfm path reg and first check */
if (hdmi_delay_normal_check > 0 &&
hdmi_delay_normal_check != 0xff &&
!hdmi_delay_first_check)
hdmi_delay_normal_check--;
/* retry n times after audio require new delay and no more check */
if (hdmin_delay_start && hdmi_delay_normal_check == 0)
hdmi_delay_normal_check = enable_hdmi_delay_normal_check;
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
}
}
static struct vframe_s *vsync_toggle_frame(struct vframe_s *vf, int line)
{
static u32 last_pts;
u32 diff_pts;
u32 first_picture = 0;
long long *clk_array;
static long long clock_vdin_last;
static long long clock_last;
ATRACE_COUNTER(__func__, line);
if (!vf)
return NULL;
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++;
#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
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;
#ifdef OLD_DI
if (vf->early_process_fun) {
if (vf->early_process_fun(vf->private_data, vf) == 1)
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 */
cur_dev->rdma_func[vpp_index].rdma_wr(DI_POST_CTRL, 0x3 << 30);
cur_dev->rdma_func[vpp_index].rdma_wr(DI_POST_SIZE,
(32 - 1) | ((128 - 1) << 16));
cur_dev->rdma_func[vpp_index].rdma_wr(DI_IF1_GEN_REG,
READ_VCBUS_REG(DI_IF1_GEN_REG) &
0xfffffffe);
}
#endif
}
#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 vf;
}
if (hold_video) {
if (cur_dispbuf != vf) {
u32 old_w, old_h;
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);
timestamp_vpts_set_u64(vf->pts_us64);
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));
timestamp_vpts_inc_u64
(DUR2PTS(last_frame_duration));
vpts_remainder +=
DUR2PTS_RM(last_frame_duration);
if (vpts_remainder >= 0xf) {
vpts_remainder -= 0xf;
timestamp_vpts_inc(-1);
timestamp_vpts_inc_u64(-1);
}
}
old_w = cur_width;
old_h = cur_height;
if (vf->type & VIDTYPE_COMPRESS) {
cur_width = vf->compWidth;
cur_height = vf->compHeight;
} else {
cur_width = vf->width;
cur_height = vf->height;
}
if (old_w != cur_width ||
old_h != cur_height)
video_prop_status |= VIDEO_PROP_CHANGE_SIZE;
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
ATRACE_COUNTER(__func__, __LINE__);
return NULL;
}
}
if (cur_dispbuf != vf) {
new_frame_count++;
if (new_frame_count == 1)
first_picture = 1;
}
if (cur_dispbuf &&
cur_dispbuf != &vf_local &&
cur_dispbuf != vf) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i = 0, done = false;
if (is_vsync_rdma_enable()) {
if (cur_rdma_buf == cur_dispbuf) {
done = check_dispbuf(cur_dispbuf, false);
if (!done) {
if (video_vf_put(cur_dispbuf) < 0)
pr_info("put err,line: %d\n",
__LINE__);
}
} else {
if (video_vf_put(cur_dispbuf) < 0) {
done = check_dispbuf(cur_dispbuf, true);
if (!done)
pr_info("put err,que full\n");
}
}
} else {
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (dispbuf_to_put[i]) {
if (!video_vf_put(dispbuf_to_put[i])) {
dispbuf_to_put[i] = NULL;
dispbuf_to_put_num--;
}
}
}
if (video_vf_put(cur_dispbuf) < 0)
check_dispbuf(cur_dispbuf, true);
}
#else
if (video_vf_put(cur_dispbuf) < 0)
check_dispbuf(cur_dispbuf, true);
#endif
if (debug_flag & DEBUG_FLAG_LATENCY) {
vf->ready_clock[3] = sched_clock();
pr_info("video toggle latency %lld us, diff %lld, get latency %lld us, vdin put latency %lld us, first %lld us, diff %lld.\n",
func_div(vf->ready_clock[3], 1000),
func_div(vf->ready_clock[3] - clock_last, 1000),
func_div(vf->ready_clock[2], 1000),
func_div(vf->ready_clock[1], 1000),
func_div(vf->ready_clock[0], 1000),
func_div(vf->ready_clock[0] -
clock_vdin_last, 1000));
clock_vdin_last = vf->ready_clock[0];
clock_last = vf->ready_clock[3];
cur_dispbuf->ready_clock[4] = sched_clock();
clk_array = cur_dispbuf->ready_clock;
pr_info("video put latency %lld us, video toggle latency %lld us, video get latency %lld us, vdin put latency %lld us, first %lld us.\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 ((debug_flag & DEBUG_FLAG_BASIC_INFO) && first_picture)
pr_info("[vpp-kpi] first toggle picture {%d,%d} pts:%x\n",
vf->width, vf->height, vf->pts);
vframe_walk_delay = (int)div_u64(((jiffies_64 -
vf->ready_jiffies64) * 1000), HZ);
if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("toggle vf %p, ready_jiffies64 %d, walk_delay %d\n",
vf, jiffies_to_msecs(vf->ready_jiffies64),
vframe_walk_delay);
/* 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);
timestamp_vpts_set_u64(vf->pts_us64);
} 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));
timestamp_vpts_inc_u64
(DUR2PTS(cur_dispbuf->duration));
vpts_remainder +=
DUR2PTS_RM(cur_dispbuf->duration);
if (vpts_remainder >= 0xf) {
vpts_remainder -= 0xf;
timestamp_vpts_inc(-1);
timestamp_vpts_inc_u64(-1);
}
}
vf->type_backup = vf->type;
}
cur_dispbuf = vf;
if (cur_dispbuf && omx_secret_mode)
cur_disp_omx_index = cur_dispbuf->omx_index;
if (first_picture) {
first_frame_toggled = 1;
#ifdef VIDEO_PTS_CHASE
av_sync_flag = 0;
#endif
}
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
}
}
ATRACE_COUNTER(__func__, 0);
return cur_dispbuf;
}
#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
/* 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 || 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, pts_temp = 0;
#ifdef VIDEO_PTS_CHASE
u32 vid_pts, scr_pts;
int aud_start = 0;
#endif
u32 systime;
u32 adjust_pts, org_vpts;
bool expired;
if (!next_vf)
return false;
if (videopeek) {
videopeek = false;
pr_info("video peek toggle 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;
/* FIXME: remove it */
if (next_vf->flag & VFRAME_FLAG_VIDEO_COMPOSER)
return true;
/*freerun for drm video*/
if (next_vf->flag & VFRAME_FLAG_VIDEO_DRM)
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;
#ifdef AVSYNC_COUNT
if (abs(timestamp_apts_get() - timestamp_vpts_get()) > 90 * 500)
av_discontinue = true;
if (abs(timestamp_apts_get() - timestamp_vpts_get()) <= 90 * 500 &&
av_discontinue) {
avsync_count++;
av_discontinue = false;
timestamp_avsync_counter_set(avsync_count);
}
#endif
if ((pts == 0 && ((cur_dispbuf && cur_dispbuf != &vf_local) ||
hold_property_changed == 1)) ||
freerun_mode == FREERUN_DUR) {
pts =
timestamp_vpts_get() +
(cur_vf ? DUR2PTS(cur_vf->duration) : 0);
if (hold_property_changed == 1)
hold_property_changed = 0;
}
/* check video PTS discontinuity */
if ((enable_video_discontinue_report) &&
(first_frame_toggled) &&
(AM_ABSSUB(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_temp = cur_vf ? DUR2PTS(cur_vf->duration) : 0;
pts = timestamp_vpts_get() + pts_temp;
if (debug_flag & DEBUG_FLAG_OMX_DEBUG_DROP_FRAME) {
pr_info("system=0x%x ,dur:%d,pts:0x%x,align:%d\n",
systime,
pts_temp, pts,
vsync_pts_align);
}
/* pr_info("system=0x%x vpts=0x%x\n", systime,*/
/*timestamp_vpts_get()); */
/* [SWPL-21116] If pts and systime diff is smaller than
* vsync_pts_align, will return true at end of this
* function and show this frame. In this bug, next_vf->pts
* is not 0 and have large diff with systime, need get into
* discontinue process and shouldn't send out this frame.
*/
if (((int)(systime - pts) >= 0) ||
(next_vf->pts > 0 &&
((int)(systime + vsync_pts_align - 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 ||
(systime < pts &&
(pts > 0xFFFFFFFF - TIME_UNIT90K)))
return true;
if (omx_secret_mode &&
cur_omx_index >= next_vf->omx_index)
return true;
return false;
} else if (omx_secret_mode &&
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 {
/* +[SE] [BUG][SWPL-21070][zihao.ling]
*when vdiscontinue, not displayed
*/
return false;
}
} else if (omx_run &&
omx_secret_mode &&
(omx_pts + omx_pts_interval_upper < next_vf->pts) &&
(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);
memset(&frame_states, 0, sizeof(struct vframe_states));
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;
}
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;
}
}
if (tsync_get_mode() == TSYNC_MODE_PCRMASTER)
expired = (timestamp_pcrscr_get() + vsync_pts_align >= pts) ?
true : false;
else
expired = (int)(timestamp_pcrscr_get() +
vsync_pts_align - pts) >= 0;
if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("vf/next %p/%p, pcr %d, pts %d, expired %d\n",
cur_vf, next_vf, timestamp_pcrscr_get(), pts, expired);
#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);
}
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) {
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name)
vf_notify_provider_by_name(provider_name,
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
static char old_vmode[32];
static char new_vmode[32];
bool tvin_vf_disp_mode_check(struct vframe_s *vf)
{
struct provider_disp_mode_req_s req;
char *vdin_name = "vdin0";
char *dv_vdin_name = "dv_vdin";
char *provider_name = NULL;
if (!vf || !(vf->source_type == VFRAME_SOURCE_TYPE_HDMI ||
vf->source_type == VFRAME_SOURCE_TYPE_CVBS ||
vf->source_type == VFRAME_SOURCE_TYPE_TUNER))
return true;
if (vf->flag & VFRAME_FLAG_KEEPED)
return true;
if (atomic_read(&vt_unreg_flag) > 0)
return true;
if (vf->source_type & (1 << 30))
provider_name = dv_vdin_name;
else
provider_name = vdin_name;
req.vf = vf;
req.disp_mode = VFRAME_DISP_MODE_NULL;
req.req_mode = 1;
if (provider_name)
vf_notify_provider_by_name(provider_name,
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
if (req.disp_mode == VFRAME_DISP_MODE_SKIP) {
pr_info("tvin need skip\n");
return false;
}
return true;
}
static inline bool video_vf_disp_mode_check(struct vframe_s *vf)
{
struct provider_disp_mode_req_s req;
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
req.vf = vf;
req.disp_mode = VFRAME_DISP_MODE_NULL;
req.req_mode = 1;
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name)
vf_notify_provider_by_name(provider_name,
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
if (req.disp_mode == VFRAME_DISP_MODE_OK ||
req.disp_mode == VFRAME_DISP_MODE_NULL)
return false;
/*set video vpts*/
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);
}
}
}
if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("video %p disp_mode %d\n", vf, req.disp_mode);
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
return true;
}
static enum vframe_disp_mode_e video_vf_disp_mode_get(struct vframe_s *vf)
{
struct provider_disp_mode_req_s req;
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
req.vf = vf;
req.disp_mode = VFRAME_DISP_MODE_NULL;
req.req_mode = 0;
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name)
vf_notify_provider_by_name(provider_name,
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
return req.disp_mode;
}
static int video_vdin_buf_info_get(void)
{
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
int max_buf_cnt = -1;
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name && (!strcmp(provider_name, "dv_vdin") ||
!strcmp(provider_name, "vdin0")))
vf_notify_provider_by_name(provider_name,
VFRAME_EVENT_RECEIVER_BUF_COUNT, (void *)&max_buf_cnt);
return max_buf_cnt;
}
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);
timestamp_vpts_set_u64(vf->pts_us64);
} 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));
timestamp_vpts_inc_u64
(DUR2PTS(cur_dispbuf->duration));
vpts_remainder +=
DUR2PTS_RM(cur_dispbuf->duration);
if (vpts_remainder >= 0xf) {
vpts_remainder -= 0xf;
timestamp_vpts_inc(-1);
timestamp_vpts_inc_u64(-1);
}
}
}
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
return true;
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static bool dvel_status;
static bool dvel_changed;
static u32 dvel_size;
static int dolby_vision_need_wait(void)
{
struct vframe_s *vf;
if (!is_dolby_vision_enable())
return 0;
vf = video_vf_peek();
if (!vf || (dolby_vision_wait_metadata(vf) == 1))
return 1;
return 0;
}
static int dolby_vision_need_wait_pip(void)
{
struct vframe_s *vf;
if (!is_dolby_vision_enable())
return 0;
vf = pip_vf_peek();
if (!vf || (dolby_vision_wait_metadata(vf) == 1))
return 1;
return 0;
}
static int dolby_vision_need_wait_pip2(void)
{
struct vframe_s *vf;
if (!is_dolby_vision_enable())
return 0;
vf = pip2_vf_peek();
if (!vf || (dolby_vision_wait_metadata(vf) == 1))
return 1;
return 0;
}
static int dvel_swap_frame(struct vframe_s *vf)
{
int ret = 0;
struct video_layer_s *layer = NULL;
struct disp_info_s *layer_info = NULL;
/* use bl layer info */
layer = &vd_layer[0];
layer_info = &glayer_info[0];
if (!is_dolby_vision_enable()) {
if (dvel_status) {
//safe_switch_videolayer(1, false, true);
dvel_status = false;
need_disable_vd2 = true;
}
} else if (vf) {
/* enable the vd2 when the first el vframe coming */
u32 new_dvel_w = (vf->type
& VIDTYPE_COMPRESS) ?
vf->compWidth :
vf->width;
/* check if el available first */
if (!dvel_status) {
dvel_changed = true;
dvel_size = new_dvel_w;
need_disable_vd2 = false;
safe_switch_videolayer(1, true, true);
}
/* check the el size */
if (dvel_size != new_dvel_w)
dvel_changed = true;
ret = set_layer_display_canvas
(layer, vf, layer->cur_frame_par,
layer_info);
dvel_status = true;
} else if (dvel_status) {
dvel_changed = true;
dvel_status = false;
dvel_size = 0;
need_disable_vd2 = true;
}
return ret;
}
/*SDK test: check metadata crc*/
/*frame crc error ---> drop err frame and repeat last frame*/
/*err count >= 6 ---> mute*/
static inline bool dv_vf_crc_check(struct vframe_s *vf)
{
bool crc_err = false;
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name && (!strcmp(provider_name, "dv_vdin") ||
!strcmp(provider_name, "vdin0"))) {
if (!vf->dv_crc_sts) {
/*drop err crc frame*/
vdin_err_crc_cnt++;
if (debug_flag & DEBUG_FLAG_HDMI_DV_CRC)
pr_info("vdin_err_crc_cnt %d\n",
vdin_err_crc_cnt);
/*need set video vpts when drop frame*/
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);
}
}
}
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
crc_err = true;
} else {
vdin_err_crc_cnt = 0;
}
} else {
vdin_err_crc_cnt = 0;
}
/*mute when err crc > = 6*/
if (vdin_err_crc_cnt >= ERR_CRC_COUNT) {
set_video_mute(true);
dv_mute_vpp_flag = true;
} else if (dv_mute_vpp_flag) {
set_video_mute(false);
dv_mute_vpp_flag = false;
}
return crc_err;
}
struct vframe_s *dvel_toggle_frame(struct vframe_s *vf, bool new_frame)
{
struct vframe_s *toggle_vf = NULL;
if (!is_dolby_vision_enable()) {
cur_dispbuf2 = NULL;
dvel_size = 0;
dvel_changed = false;
return NULL;
}
if (new_frame) {
int ret = dolby_vision_update_metadata(vf, false);
if (!is_dolby_vision_el_disable() ||
for_dolby_vision_certification())
cur_dispbuf2 = dolby_vision_vf_peek_el(vf);
if (ret == 0) {
/* setting generated for this frame */
/* or DOVI in bypass mode */
toggle_vf = vf;
dolby_vision_set_toggle_flag(1);
} else if (ret == 1) {
/* both dolby and hdr module bypass */
toggle_vf = vf;
dolby_vision_set_toggle_flag(0);
} else {
/* fail generating setting for this frame */
toggle_vf = NULL;
dolby_vision_set_toggle_flag(0);
}
} else {
/* FIXME: if need the is on condition */
/* if (is_dolby_vision_on() && get_video_enabled()) */
if (!dolby_vision_parse_metadata(vf, 2, false, false))
dolby_vision_set_toggle_flag(1);
}
return toggle_vf;
}
static void dolby_vision_proc(struct video_layer_s *layer,
struct vpp_frame_par_s *cur_frame_par)
{
static struct vframe_s *cur_dv_vf;
static u32 cur_frame_size;
struct vframe_s *disp_vf;
u8 toggle_mode;
if (is_dolby_vision_enable()) {
u32 frame_size = 0, h_size, v_size;
u8 pps_state = 0; /* pps no change */
/* TODO: check if need */
#ifdef OLD_DV_FLOW
/* force toggle when keeping frame after playing */
if (is_local_vf(layer->dispbuf) &&
!layer->new_frame &&
is_dolby_vision_video_on() &&
get_video_enabled()) {
if (!dolby_vision_parse_metadata
(layer->dispbuf, 2, false, false))
dolby_vision_set_toggle_flag(1);
}
#endif
if (layer->new_frame)
toggle_mode = 1; /* new frame */
else if (!layer->dispbuf ||
is_local_vf(layer->dispbuf))
toggle_mode = 2; /* keep frame */
else
toggle_mode = 0; /* pasue frame */
if (layer->switch_vf && layer->vf_ext)
disp_vf = layer->vf_ext;
else
disp_vf = layer->dispbuf;
if (cur_frame_par) {
if (layer->new_vpp_setting) {
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 &&
layer->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 (disp_vf) {
h_size = (disp_vf->type & VIDTYPE_COMPRESS) ?
disp_vf->compWidth : disp_vf->width;
v_size = (disp_vf->type & VIDTYPE_COMPRESS) ?
disp_vf->compHeight : disp_vf->height;
frame_size = (h_size << 16) | v_size;
}
/* trigger dv process once when stop playing */
/* because disp_vf is not sync with video off */
if (cur_dv_vf && !disp_vf)
dolby_vision_set_toggle_flag(1);
cur_dv_vf = disp_vf;
if (cur_frame_size != frame_size) {
cur_frame_size = frame_size;
dolby_vision_set_toggle_flag(1);
}
dolby_vision_process
(disp_vf, frame_size,
toggle_mode, pps_state);
dolby_vision_update_setting();
}
}
/* 1: drop fail; 0: drop success*/
static int dolby_vision_drop_frame(void)
{
struct vframe_s *vf;
if (dolby_vision_need_wait()) {
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("drop frame need wait!\n");
return 1;
}
vf = video_vf_get();
if (vf && (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME))
pr_info("drop vf %p, index %d, pts %d\n",
vf, vf->omx_index, vf->pts);
dolby_vision_update_metadata(vf, true);
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("drop vf %p done\n", vf);
return 0;
}
#endif
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
/* 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;
}
}
#endif
#define VDIN_KEEP_COUNT 1
#define DI_KEEP_COUNT_P 1
#define DI_KEEP_COUNT_I 2
#define DIS_PATH_DELAY_COUNT 2
#define VDIN_BUF_COUNT 11
#define DI_MAX_OUT_COUNT 9
#define VLOCL_DELAY 7 /*vdin vsync before vpp vsync about 7ms*/
static void hdmi_in_delay_maxmin_reset(void)
{
hdmin_delay_min_ms = 0;
hdmin_delay_max_ms = 0;
}
static void hdmi_in_delay_maxmin_old(struct vframe_s *vf)
{
u64 vdin_vsync = 0;
u64 vpp_vsync = 0;
u32 vdin_count = 0;
int di_keep_count = 0;
u64 hdmin_delay_min = 0;
u64 hdmin_delay_max = 0;
int buf_cnt;
struct vinfo_s *video_info;
u64 memc_delay = 0;
int vdin_keep_count = VDIN_KEEP_COUNT;
if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI &&
vf->source_type != VFRAME_SOURCE_TYPE_CVBS &&
vf->source_type != VFRAME_SOURCE_TYPE_TUNER)
return;
if (vf->type & VIDTYPE_DI_PW) {
if (vf->type_original & VIDTYPE_INTERLACE)
di_keep_count = DI_KEEP_COUNT_I;
else
di_keep_count = DI_KEEP_COUNT_P;
}
#ifdef CONFIG_AMLOGIC_MEDIA_VDIN
vdin_keep_count += get_vdin_add_delay_num();
#endif
video_info = get_current_vinfo();
if (video_info->sync_duration_num > 0) {
vpp_vsync = video_info->sync_duration_den;
vpp_vsync = vpp_vsync * 1000000;
vpp_vsync = div64_u64(vpp_vsync,
video_info->sync_duration_num);
}
vdin_vsync = vf->duration;
vdin_vsync = vdin_vsync * 1000;
vdin_vsync = div64_u64(vdin_vsync, 96);
#ifdef CONFIG_AMLOGIC_MEDIA_FRC
memc_delay = frc_get_video_latency();
#endif
/*pre: vdin keep 1, di keep 1/2(one process,one for I frame), total 2/3
*rdma one vpp vsync, one for next vsync to peek
*if do di: count = (1 + 1/2) * vdin_vsync + vpp_vsync * 2;
*if no di: count = (1 + 0) * vdin_vsync + vpp_vsync * 2;
*/
hdmin_delay_min = (vdin_keep_count + di_keep_count) * vdin_vsync
+ vpp_vsync * 2;
hdmin_delay_min_ms = div64_u64(hdmin_delay_min, 1000);
hdmin_delay_min_ms += memc_delay;
/*vdin total 10 buf, one for vdin next write, one is on display, 8 left
*/
buf_cnt = video_vdin_buf_info_get();
if (buf_cnt <= 2)
return;
vdin_count = buf_cnt - 1 - 1;
hdmin_delay_max = vdin_count * vdin_vsync;
hdmin_delay_max_ms = div64_u64(hdmin_delay_max, 1000);
hdmin_delay_max_ms += memc_delay;
}
static void hdmi_in_delay_maxmin_new(struct vframe_s *vf)
{
u64 vdin_vsync = 0;
u64 vpp_vsync = 0;
u32 vdin_count = 0;
u32 vpp_count = 0;
int di_keep_count = 0;
bool do_di = false;
bool di_has_vdin_vf = false;
u64 hdmin_delay_min = 0;
u64 hdmin_delay_max = 0;
u64 memc_delay = 0;
int vdin_keep_count = VDIN_KEEP_COUNT;
unsigned int ret_hz = 0;
u64 ext_delay = 0;
if (!tvin_delay_mode)
return;
if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI &&
vf->source_type != VFRAME_SOURCE_TYPE_CVBS &&
vf->source_type != VFRAME_SOURCE_TYPE_TUNER)
return;
if (vf->type & VIDTYPE_DI_PW) {
if (vf->type_original & VIDTYPE_INTERLACE)
di_keep_count = DI_KEEP_COUNT_I;
else
di_keep_count = DI_KEEP_COUNT_P;
do_di = true;
if (vf->flag & VFRAME_FLAG_DOUBLE_FRAM)
di_has_vdin_vf = true;
}
#ifdef CONFIG_AMLOGIC_MEDIA_VDIN
vdin_keep_count += get_vdin_add_delay_num();
#endif
vdin_vsync = vf->duration;
vdin_vsync = vdin_vsync * 1000;
vdin_vsync = div64_u64(vdin_vsync, 96);
vpp_vsync = vsync_pts_inc_scale;
vpp_vsync = vpp_vsync * 1000000;
vpp_vsync = div64_u64(vpp_vsync, vsync_pts_inc_scale_base);
#ifdef CONFIG_AMLOGIC_MEDIA_FRC
memc_delay = frc_get_video_latency();
#endif
if (vf->duration != 0)
ret_hz = (96000 + vf->duration / 2) / vf->duration;
if (ret_hz >= 25)
ext_delay = VLOCL_DELAY * 1000;
else
ext_delay = vpp_vsync;
/*pre: vdin keep 1, di keep 1/2(p:1; I:2, one process), total 2/3
*I frame di will keep two, P frame keep one,
*post:disp path 2 buf delay(vq->vpp 1 buf, rdma one buf),
*if do di: count = (1 + 1/2) * vdin_vsync + 2 * vpp_vsync;
*if no di: count = (1 + 0) * vdin_vsync + 2* vpp_vsync;
*vdin vsync before vpp vsync about 7ms
*/
hdmin_delay_min = (vdin_keep_count + di_keep_count) * vdin_vsync +
DIS_PATH_DELAY_COUNT * vpp_vsync + ext_delay;
hdmin_delay_min_ms = div64_u64(hdmin_delay_min, 1000);
hdmin_delay_min_ms += memc_delay;
/*case 1:vdin vf sent to vpp:
*vdin total 11 buf, one for vdin next write, one vdin write, 9 left
*one is on display, 8 left
*disp path 2 buf delay(vq->vpp 1 buf, rdma one buf),
*one for vq next vsync to get, 5 left
*count = VDIN_BUF_COUNT - 1 -1 -1 -DIS_PATH_DELAY_COUNT - 1 = 5;
*total delay = 5 * vdin_vsync + 3 * vpp_vsync;
*
* case 2:vdin vf not sent to vpp:
*2.1:di max out 9,one on display, one for vq next vsync to get, 7 left
*2.2:vdin total 11, one for vdin next write, one vdin write, 9 left
*di keep 1/2 buf, 8/7 left
*count = (7 + 8/7) * vdin_vsync+ 3 * vpp_vsync;
*/
if (di_has_vdin_vf || !do_di) {
vdin_count = VDIN_BUF_COUNT - 3 - DIS_PATH_DELAY_COUNT - 1;
vpp_count = DIS_PATH_DELAY_COUNT + 1;
} else {
vdin_count = DI_MAX_OUT_COUNT - 2 +
VDIN_BUF_COUNT - 2 - di_keep_count;
vpp_count = DIS_PATH_DELAY_COUNT + 1;
}
hdmin_delay_max = vdin_count * vdin_vsync + vpp_count * vpp_vsync;
hdmin_delay_max_ms = div64_u64(hdmin_delay_max, 1000);
hdmin_delay_max_ms += memc_delay;
}
static void hdmi_in_delay_maxmin_new1(struct tvin_to_vpp_info_s *tvin_info)
{
u64 vdin_vsync = 0;
u64 vpp_vsync = 0;
u32 vdin_count = 0;
u32 vpp_count = 0;
int di_keep_count = 0;
bool do_di = false;
bool di_has_vdin_vf = false;
u64 hdmin_delay_min = 0;
u64 hdmin_delay_max = 0;
u64 memc_delay = 0;
int vdin_keep_count = VDIN_KEEP_COUNT;
u64 ext_delay = 0;
if (!tvin_info->is_dv && tvin_info->width <= 3840 &&
tvin_info->cfmt == TVIN_YUV422) {
do_di = true;
if (tvin_info->width > 1920 && tvin_info->width <= 3840)
di_has_vdin_vf = true;
if (tvin_info->scan_mode == TVIN_SCAN_MODE_INTERLACED)
di_keep_count = DI_KEEP_COUNT_I;
else
di_keep_count = DI_KEEP_COUNT_P;
}
#ifdef CONFIG_AMLOGIC_MEDIA_VDIN
vdin_keep_count += get_vdin_add_delay_num();
#endif
vdin_vsync = div64_u64(1000 * 1000, tvin_info->fps);
if (tvin_info->fps == 50 || tvin_info->fps == 25)
vpp_vsync = div64_u64(1000 * 1000, 50);
else
vpp_vsync = div64_u64(1000 * 1000, 60);
#ifdef CONFIG_AMLOGIC_MEDIA_FRC
memc_delay = frc_get_video_latency();
#endif
if (tvin_info->fps >= 25)
ext_delay = VLOCL_DELAY * 1000;
else
ext_delay = vpp_vsync;
/*pre: vdin keep 1, di keep 1/2(p:1; I:2, one process), total 2/3
*I frame di will keep two, P frame keep one,
*post:disp path 2 buf delay(vq->vpp 1 buf, rdma one buf),
*if do di: count = (1 + 1/2) * vdin_vsync + 2 * vpp_vsync;
*if no di: count = (1 + 0) * vdin_vsync + 2* vpp_vsync;
*vdin vsync before vpp vsync about 7ms
*/
hdmin_delay_min = (vdin_keep_count + di_keep_count) * vdin_vsync +
DIS_PATH_DELAY_COUNT * vpp_vsync + ext_delay;
hdmin_delay_min_ms = div64_u64(hdmin_delay_min, 1000);
hdmin_delay_min_ms += memc_delay;
/*case 1:vdin vf sent to vpp:
*vdin total 11 buf, one for vdin next write, one vdin write, 9 left
*one is on display, 8 left
*disp path 2 buf delay(vq->vpp 1 buf, rdma one buf),
*one for vq next vsync to get, 5 left
*count = VDIN_BUF_COUNT - 1 -1 -1 -DIS_PATH_DELAY_COUNT - 1 = 5;
*total delay = 5 * vdin_vsync + 3 * vpp_vsync;
*
* case 2:vdin vf not sent to vpp:
*2.1:di max out 9,one on display, one for vq next vsync to get, 7 left
*2.2:vdin total 11, one for vdin next write, one vdin write, 9 left
*di keep 1/2 buf, 8/7 left
*count = (7 + 8/7) * vdin_vsync+ 3 * vpp_vsync;
*/
if (di_has_vdin_vf || !do_di) {
vdin_count = VDIN_BUF_COUNT - 3 - DIS_PATH_DELAY_COUNT - 1;
vpp_count = DIS_PATH_DELAY_COUNT + 1;
} else {
vdin_count = DI_MAX_OUT_COUNT - 2 +
VDIN_BUF_COUNT - 2 - di_keep_count;
vpp_count = DIS_PATH_DELAY_COUNT + 1;
}
hdmin_delay_max = vdin_count * vdin_vsync + vpp_count * vpp_vsync;
hdmin_delay_max_ms = div64_u64(hdmin_delay_max, 1000);
hdmin_delay_max_ms += memc_delay;
pr_info("cfmt=%d, scan=%d,%d*%d, isdv=%d (%d, %d)\n",
tvin_info->cfmt,
tvin_info->scan_mode,
tvin_info->width,
tvin_info->height,
tvin_info->is_dv,
hdmin_delay_min_ms,
hdmin_delay_max_ms);
}
void vdin_start_notify_vpp(struct tvin_to_vpp_info_s *tvin_info)
{
tvin_delay_mode = 1;
if (vf_check_node("videoqueue.0"))
hdmi_in_delay_maxmin_new1(tvin_info);
}
EXPORT_SYMBOL(vdin_start_notify_vpp);
u32 get_tvin_delay_start(void)
{
return hdmin_delay_start;
}
EXPORT_SYMBOL(get_tvin_delay_start);
void set_tvin_delay_start(u32 start)
{
hdmin_delay_start = start;
}
EXPORT_SYMBOL(set_tvin_delay_start);
u32 get_tvin_delay_duration(void)
{
return last_required_total_delay;
}
EXPORT_SYMBOL(get_tvin_delay_duration);
void set_tvin_delay_duration(u32 time)
{
last_required_total_delay = time;
}
EXPORT_SYMBOL(set_tvin_delay_duration);
u32 get_tvin_delay(void)
{
return vframe_walk_delay;
}
EXPORT_SYMBOL(get_tvin_delay);
u32 get_tvin_delay_max_ms(void)
{
return hdmin_delay_max_ms;
}
EXPORT_SYMBOL(get_tvin_delay_max_ms);
u32 get_tvin_delay_min_ms(void)
{
return hdmin_delay_min_ms;
}
EXPORT_SYMBOL(get_tvin_delay_min_ms);
static bool tvin_vf_is_keeped(struct vframe_s *vf)
{
struct vframe_s *src_vf;
if (!vf)
return false;
if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI &&
vf->source_type != VFRAME_SOURCE_TYPE_CVBS &&
vf->source_type != VFRAME_SOURCE_TYPE_TUNER)
return false;
if (!(vf->flag & VFRAME_FLAG_VIDEO_COMPOSER_BYPASS))
return false;
if (!vf->vc_private)
return false;
src_vf = vf->vc_private->src_vf;
if (!src_vf)
return false;
if (src_vf->flag & VFRAME_FLAG_KEEPED)
return true;
return false;
}
/*ret = 0: no need delay*/
/*ret = 1: need to delay*/
static int hdmi_in_delay_check(struct vframe_s *vf)
{
int expire;
int vsync_duration = 0;
u64 pts;
u64 us;
unsigned long flags;
int expire_align = 0;
char *provider_name = vf_get_provider_name(RECEIVER_NAME);
if (hdmin_delay_done)
return 0;
if (!vf || vf->duration == 0)
return 0;
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (!provider_name || (strcmp(provider_name, "dv_vdin") &&
strcmp(provider_name, "vdin0"))) {
return 0;
}
spin_lock_irqsave(&hdmi_avsync_lock, flags);
/* update duration */
vsync_duration = (int)(vf->duration / 96);
if (hdmin_delay_start_time == -1) {
hdmin_delay_start_time = jiffies_to_msecs(jiffies);
/*this funtcion lead to one vsync delay */
/*hdmin_delay_start_time -= vsync_duration;*/
if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("vsync_duration %d, hdmin_delay_start_time %d\n",
vsync_duration, hdmin_delay_start_time);
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
return 1;
}
expire = jiffies_to_msecs(jiffies) -
hdmin_delay_start_time;
if (last_required_total_delay >= hdmin_delay_max_ms) {
/*when required more than hdmin_delay_max_ms, */
expire_align = -vsync_duration;
} else {
/*delay one more vsync? select the one that closer to required*/
expire_align = -vsync_duration / 2;
}
if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("expire %d, hdmin_delay_duration %d, expire_align %d\n",
expire, hdmin_delay_duration, expire_align);
if (expire - hdmin_delay_duration <= expire_align) {
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
return 1;
}
hdmin_delay_done = true;
if (debug_flag & DEBUG_FLAG_HDMI_AVSYNC_DEBUG)
pr_info("hdmi video delay done! expire %d\n", expire);
/*reset vpts=pcr will lead vpts_expire delay 1 vsync - vsync_pts_align*/
timestamp_vpts_set(timestamp_pcrscr_get() - (DUR2PTS(vf->duration) - vsync_pts_align));
timestamp_vpts_set_u64((u64)(timestamp_pcrscr_get() -
(DUR2PTS(vf->duration) - vsync_pts_align)));
pts = (u64)timestamp_pcrscr_get_u64();
pts = pts - (DUR2PTS(vf->duration) - vsync_pts_align);
us = div64_u64(pts * 100, 9);
timestamp_vpts_set_u64(us);
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
return 0;
}
static void hdmi_in_drop_frame(void)
{
struct vframe_s *vf;
while (hdmin_need_drop_count > 0) {
vf = video_vf_get();
if (!vf) { /*no video frame, drop done*/
/*hdmi_need_drop_count = 0;*/
break;
}
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
if (debug_flag & DEBUG_FLAG_PRINT_DROP_FRAME)
pr_info("#line %d: drop %p\n", __LINE__, vf);
video_drop_vf_cnt++;
--hdmin_need_drop_count;
}
}
#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
bool black_threshold_check(u8 id)
{
struct video_layer_s *layer = NULL;
struct disp_info_s *layer_info = NULL;
struct vpp_frame_par_s *frame_par = NULL;
bool ret = false;
if (id >= MAX_VD_LAYERS)
return ret;
if (black_threshold_width <= 0 ||
black_threshold_height <= 0)
return ret;
layer = &vd_layer[id];
layer_info = &glayer_info[id];
if (layer_info->layer_top == 0 &&
layer_info->layer_left == 0 &&
layer_info->layer_width <= 1 &&
layer_info->layer_height <= 1)
/* special case to do full screen display */
return ret;
frame_par = layer->cur_frame_par;
if (layer_info->layer_width <= black_threshold_width ||
layer_info->layer_height <= black_threshold_height) {
if (frame_par &&
frame_par->vscale_skip_count == 8 &&
frame_par->hscale_skip_count == 1)
ret = true;
}
return ret;
}
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;
layer->crop_top = p[0];
layer->crop_left = p[1];
layer->crop_bottom = p[2];
layer->crop_right = p[3];
new_t = layer->crop_top;
new_l = layer->crop_left;
new_b = layer->crop_bottom;
new_r = layer->crop_right;
if (new_t != last_t || new_l != last_l ||
new_b != last_b || new_r != last_r) {
if (layer->layer_id == 0) {
vd_layer[0].property_changed = true;
} else if (layer->layer_id == 1) {
if (vd_layer[1].vpp_index == VPP0)
vd_layer[1].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
} else if (layer->layer_id == 2) {
if (vd_layer[2].vpp_index == VPP0)
vd_layer[2].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
}
}
}
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
if (reverse) {
temp = parsed[0];
temp1 = parsed[1];
if (get_osd_reverse() & 1) {
parsed[0] = info->width - parsed[2] - 1;
parsed[2] = info->width - temp - 1;
}
if (get_osd_reverse() & 2) {
parsed[1] = info->height - parsed[3] - 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;
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;
trace_axis("VIDEO",
layer->layer_left,
layer->layer_top,
layer->layer_left + layer->layer_width - 1,
layer->layer_top + layer->layer_height - 1);
if (last_x != new_x || last_y != new_y ||
last_w != new_w || last_h != new_h) {
if (layer->layer_id == 0) {
atomic_set(&axis_changed, 1);
vd_layer[0].property_changed = true;
if (debug_flag & DEBUG_FLAG_TRACE_EVENT)
pr_info("VD1 axis changed: %d %d (%d %d)->%d %d (%d %d)\n",
last_x, last_y, last_w, last_h,
new_x, new_y, new_w, new_h);
} else if (layer->layer_id == 1) {
if (vd_layer[1].vpp_index == VPP0)
vd_layer[1].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
} else if (layer->layer_id == 2) {
if (vd_layer[2].vpp_index == VPP0)
vd_layer[2].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
}
}
}
void _set_video_mirror(struct disp_info_s *layer, int mirror)
{
int last_mirror, new_mirror;
bool revser_temp = false;
if (!layer)
return;
#ifdef TV_REVERSE
if (reverse) {
revser_temp = true;
if (mirror == H_MIRROR) {
mirror = V_MIRROR;
revser_temp = false;
} else if (mirror == V_MIRROR) {
mirror = H_MIRROR;
revser_temp = false;
}
}
#endif
last_mirror = layer->mirror;
new_mirror = mirror;
layer->mirror = mirror;
layer->reverse = revser_temp;
if (last_mirror != new_mirror) {
if (layer->layer_id == 0) {
vd_layer[0].property_changed = true;
if (debug_flag & DEBUG_FLAG_TRACE_EVENT)
pr_info("VD1 mirror changed: %d ->%d\n",
last_mirror, new_mirror);
} else if (layer->layer_id == 1) {
if (vd_layer[1].vpp_index == VPP0)
vd_layer[1].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
} else if (layer->layer_id == 2) {
if (vd_layer[2].vpp_index == VPP0)
vd_layer[2].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
}
}
}
void set_video_crop_ext(int layer_index, int *p)
{
struct disp_info_s *layer = &glayer_info[layer_index];
_set_video_crop(layer, p);
}
void set_video_window_ext(int layer_index, int *p)
{
struct disp_info_s *layer = &glayer_info[layer_index];
if (!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE))
_set_video_window(layer, p);
}
void set_video_zorder_ext(int layer_index, int zorder)
{
struct disp_info_s *layer = &glayer_info[layer_index];
if (layer->zorder != zorder) {
layer->zorder = zorder;
if (layer->layer_id == 0)
vd_layer[0].property_changed = true;
else if (layer->layer_id == 1) {
if (vd_layer[1].vpp_index == VPP0)
vd_layer[1].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
} else if (layer->layer_id == 2) {
if (vd_layer[2].vpp_index == VPP0)
vd_layer[2].property_changed = true;
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer->layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
vd_layer_vpp[0].property_changed = true;
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer->layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
vd_layer_vpp[1].property_changed = true;
}
}
}
void pip2_swap_frame(struct video_layer_s *layer, struct vframe_s *vf,
const struct vinfo_s *vinfo)
{
struct disp_info_s *layer_info;
int axis[4];
int crop[4];
if (!vf)
return;
layer_info = &glayer_info[2];
if (layer->global_debug &
DEBUG_FLAG_PRINT_TOGGLE_FRAME)
pr_info("%s()\n", __func__);
if ((vf->flag & (VFRAME_FLAG_VIDEO_COMPOSER |
VFRAME_FLAG_VIDEO_DRM)) &&
!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) {
int mirror = 0;
axis[0] = vf->axis[0];
axis[1] = vf->axis[1];
axis[2] = vf->axis[2];
axis[3] = vf->axis[3];
crop[0] = vf->crop[0];
crop[1] = vf->crop[1];
crop[2] = vf->crop[2];
crop[3] = vf->crop[3];
_set_video_window(layer_info, axis);
if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI &&
vf->source_type != VFRAME_SOURCE_TYPE_CVBS &&
vf->source_type != VFRAME_SOURCE_TYPE_TUNER &&
vf->source_type != VFRAME_SOURCE_TYPE_HWC)
_set_video_crop(layer_info, crop);
if (vf->flag & VFRAME_FLAG_MIRROR_H)
mirror = H_MIRROR;
if (vf->flag & VFRAME_FLAG_MIRROR_V)
mirror = V_MIRROR;
_set_video_mirror(layer_info, mirror);
layer_info->zorder = vf->zorder;
}
layer_swap_frame(vf, layer, false, vinfo);
/* FIXME: free correct keep frame */
if (!is_local_vf(layer->dispbuf)) {
if (layer->keep_frame_id == 2)
video_pip2_keeper_new_frame_notify();
else if (layer->keep_frame_id == 1)
video_pip_keeper_new_frame_notify();
else if (layer->keep_frame_id == 0)
video_keeper_new_frame_notify();
}
fgrain_update_table(layer, vf);
if (stop_update)
layer->new_vpp_setting = false;
}
s32 pip2_render_frame(struct video_layer_s *layer, const struct vinfo_s *vinfo)
{
struct vpp_frame_par_s *frame_par;
u32 zoom_start_y, zoom_end_y;
bool force_setting = false;
struct vframe_s *dispbuf = NULL;
if (!layer)
return -1;
if (layer->new_vpp_setting) {
layer->cur_frame_par = layer->next_frame_par;
/* just keep the order variable */
curpip2_frame_par = layer->cur_frame_par;
}
if (glayer_info[layer->layer_id].fgrain_force_update) {
force_setting = true;
glayer_info[layer->layer_id].fgrain_force_update = false;
}
frame_par = layer->cur_frame_par;
if (layer->switch_vf && layer->vf_ext)
dispbuf = layer->vf_ext;
else
dispbuf = layer->dispbuf;
/* process cur frame for each vsync */
if (dispbuf) {
int need_afbc =
(dispbuf->type & VIDTYPE_COMPRESS);
int afbc_need_reset =
(layer->enabled && need_afbc &&
!is_afbc_enabled(layer->layer_id));
/*video on && afbc is off && is compress frame.*/
if (layer->new_vpp_setting || afbc_need_reset)
vd_set_dcu
(layer->layer_id, layer,
frame_par, dispbuf);
/* for vout change or interlace frame */
proc_vd_vsc_phase_per_vsync
(layer,
frame_par, dispbuf);
}
if (!layer->new_vpp_setting && !force_setting) {
/* when new frame is toggled but video layer is not on */
/* need always flush pps register before pwr on */
/* to avoid pps coeff lost */
if (frame_par && dispbuf && !is_local_vf(dispbuf) &&
(!get_videopip2_enabled() ||
get_videopip2_onoff_state() ==
VIDEO_ENABLE_STATE_ON_PENDING))
vd_scaler_setting(layer, &layer->sc_setting);
return 0;
}
if (dispbuf) {
/* progressive or decode interlace case height 1:1 */
zoom_start_y = frame_par->VPP_vd_start_lines_;
zoom_end_y = frame_par->VPP_vd_end_lines_;
if (dispbuf &&
(dispbuf->type & VIDTYPE_INTERLACE) &&
(dispbuf->type & VIDTYPE_VIU_FIELD)) {
/* vdin interlace frame case height/2 */
zoom_start_y /= 2;
zoom_end_y = ((zoom_end_y + 1) >> 1) - 1;
}
layer->start_x_lines = frame_par->VPP_hd_start_lines_;
layer->end_x_lines = frame_par->VPP_hd_end_lines_;
layer->start_y_lines = zoom_start_y;
layer->end_y_lines = zoom_end_y;
config_vd_position
(layer, &layer->mif_setting);
vd_mif_setting
(layer, &layer->mif_setting);
fgrain_config(layer,
layer->cur_frame_par,
&layer->mif_setting,
&layer->fgrain_setting,
dispbuf);
}
config_vd_pps
(layer, &layer->sc_setting, vinfo);
vd_scaler_setting
(layer, &layer->sc_setting);
config_vd_blend
(layer, &layer->bld_setting);
vd_blend_setting
(layer, &layer->bld_setting);
if (layer->vpp_index != VPP0)
vppx_vd_blend_setting
(layer, &layer->bld_setting);
fgrain_setting(layer,
&layer->fgrain_setting,
dispbuf);
layer->new_vpp_setting = false;
return 1;
}
void pip_swap_frame(struct video_layer_s *layer, struct vframe_s *vf,
const struct vinfo_s *vinfo)
{
struct disp_info_s *layer_info;
int axis[4];
int crop[4];
if (!vf)
return;
layer_info = &glayer_info[1];
if (layer->global_debug &
DEBUG_FLAG_PRINT_TOGGLE_FRAME)
pr_info("%s()\n", __func__);
if ((vf->flag & (VFRAME_FLAG_VIDEO_COMPOSER |
VFRAME_FLAG_VIDEO_DRM)) &&
!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) {
int mirror = 0;
axis[0] = vf->axis[0];
axis[1] = vf->axis[1];
axis[2] = vf->axis[2];
axis[3] = vf->axis[3];
crop[0] = vf->crop[0];
crop[1] = vf->crop[1];
crop[2] = vf->crop[2];
crop[3] = vf->crop[3];
_set_video_window(layer_info, axis);
if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI &&
vf->source_type != VFRAME_SOURCE_TYPE_CVBS &&
vf->source_type != VFRAME_SOURCE_TYPE_TUNER &&
vf->source_type != VFRAME_SOURCE_TYPE_HWC)
_set_video_crop(layer_info, crop);
if (vf->flag & VFRAME_FLAG_MIRROR_H)
mirror = H_MIRROR;
if (vf->flag & VFRAME_FLAG_MIRROR_V)
mirror = V_MIRROR;
_set_video_mirror(layer_info, mirror);
layer_info->zorder = vf->zorder;
}
layer_swap_frame(vf, layer, false, vinfo);
/* FIXME: free correct keep frame */
if (!is_local_vf(layer->dispbuf)) {
if (layer->keep_frame_id == 1)
video_pip_keeper_new_frame_notify();
else if (layer->keep_frame_id == 0)
video_keeper_new_frame_notify();
}
fgrain_update_table(layer, vf);
if (stop_update)
layer->new_vpp_setting = false;
}
s32 pip_render_frame(struct video_layer_s *layer, const struct vinfo_s *vinfo)
{
struct vpp_frame_par_s *frame_par;
u32 zoom_start_y, zoom_end_y;
struct vframe_s *dispbuf = NULL;
bool force_setting = false;
if (!layer)
return -1;
if (layer->new_vpp_setting) {
layer->cur_frame_par = layer->next_frame_par;
/* just keep the order variable */
curpip_frame_par = layer->cur_frame_par;
}
if (glayer_info[layer->layer_id].fgrain_force_update) {
force_setting = true;
glayer_info[layer->layer_id].fgrain_force_update = false;
}
frame_par = layer->cur_frame_par;
if (layer->switch_vf && layer->vf_ext)
dispbuf = layer->vf_ext;
else
dispbuf = layer->dispbuf;
/* process cur frame for each vsync */
if (dispbuf) {
int need_afbc =
(dispbuf->type & VIDTYPE_COMPRESS);
int afbc_need_reset =
(layer->enabled && need_afbc &&
!is_afbc_enabled(layer->layer_id));
/*video on && afbc is off && is compress frame.*/
if (layer->new_vpp_setting || afbc_need_reset)
vd_set_dcu
(layer->layer_id, layer,
frame_par, dispbuf);
/* for vout change or interlace frame */
proc_vd_vsc_phase_per_vsync
(layer,
frame_par, dispbuf);
}
if (!layer->new_vpp_setting && !force_setting) {
/* when new frame is toggled but video layer is not on */
/* need always flush pps register before pwr on */
/* to avoid pps coeff lost */
if (frame_par && dispbuf && !is_local_vf(dispbuf) &&
(!get_videopip_enabled() ||
get_videopip_onoff_state() ==
VIDEO_ENABLE_STATE_ON_PENDING))
vd_scaler_setting(layer, &layer->sc_setting);
return 0;
}
if (dispbuf) {
/* progressive or decode interlace case height 1:1 */
zoom_start_y = frame_par->VPP_vd_start_lines_;
zoom_end_y = frame_par->VPP_vd_end_lines_;
if (dispbuf &&
(dispbuf->type & VIDTYPE_INTERLACE) &&
(dispbuf->type & VIDTYPE_VIU_FIELD)) {
/* vdin interlace frame case height/2 */
zoom_start_y /= 2;
zoom_end_y = ((zoom_end_y + 1) >> 1) - 1;
}
layer->start_x_lines = frame_par->VPP_hd_start_lines_;
layer->end_x_lines = frame_par->VPP_hd_end_lines_;
layer->start_y_lines = zoom_start_y;
layer->end_y_lines = zoom_end_y;
config_vd_position
(layer, &layer->mif_setting);
vd_mif_setting
(layer, &layer->mif_setting);
fgrain_config(layer,
layer->cur_frame_par,
&layer->mif_setting,
&layer->fgrain_setting,
dispbuf);
}
config_vd_pps
(layer, &layer->sc_setting, vinfo);
vd_scaler_setting
(layer, &layer->sc_setting);
config_vd_blend
(layer, &layer->bld_setting);
vd_blend_setting
(layer, &layer->bld_setting);
if (layer->vpp_index != VPP0)
vppx_vd_blend_setting
(layer, &layer->bld_setting);
fgrain_setting(layer,
&layer->fgrain_setting,
dispbuf);
layer->new_vpp_setting = false;
return 1;
}
static void primary_swap_frame(struct video_layer_s *layer, struct vframe_s *vf1, int line)
{
bool vf_with_el = false;
bool force_toggle = false;
int ret;
struct disp_info_s *layer_info = NULL;
int axis[4];
int crop[4];
struct vframe_s *vf;
u32 vpp_index = 0;
ATRACE_COUNTER(__func__, line);
if (!vf1)
return;
vf = vf1;
layer_info = &glayer_info[0];
if (layer->need_switch_vf && IS_DI_POST(vf->type)) {
if ((vf1->flag & VFRAME_FLAG_DOUBLE_FRAM) &&
is_di_post_mode(vf1)) {
if (di_api_get_instance_id() == vf1->di_instance_id) {
layer->need_switch_vf = false;
pr_info("set need_switch_vf false\n");
} else {
vf = vf1->vf_ext;
layer->do_switch = true;
di_api_post_disable();
}
} else {
layer->need_switch_vf = false;
}
}
if ((vf->flag & (VFRAME_FLAG_VIDEO_COMPOSER |
VFRAME_FLAG_VIDEO_DRM)) &&
!(vf->flag & VFRAME_FLAG_FAKE_FRAME) &&
!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) {
int mirror = 0;
axis[0] = vf->axis[0];
axis[1] = vf->axis[1];
axis[2] = vf->axis[2];
axis[3] = vf->axis[3];
crop[0] = vf->crop[0];
crop[1] = vf->crop[1];
crop[2] = vf->crop[2];
crop[3] = vf->crop[3];
_set_video_window(&glayer_info[0], axis);
if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI &&
vf->source_type != VFRAME_SOURCE_TYPE_CVBS &&
vf->source_type != VFRAME_SOURCE_TYPE_TUNER &&
vf->source_type != VFRAME_SOURCE_TYPE_HWC)
_set_video_crop(&glayer_info[0], crop);
if (vf->flag & VFRAME_FLAG_MIRROR_H)
mirror = H_MIRROR;
if (vf->flag & VFRAME_FLAG_MIRROR_V)
mirror = V_MIRROR;
_set_video_mirror(&glayer_info[0], mirror);
glayer_info[0].zorder = vf->zorder;
}
if (layer->layer_id == 0 &&
!(vf->type & VIDTYPE_COMPRESS) &&
layer_info->need_no_compress) {
atomic_sub(1, &gafbc_request);
layer_info->need_no_compress = false;
force_toggle = true;
}
if (is_dolby_vision_enable())
vf_with_el = has_enhanced_layer(vf);
/* FIXME: need check the pre seq */
if (vf->early_process_fun) {
if (vf->early_process_fun(vf->private_data, vf) == 1)
force_toggle = true;
} else {
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
/* FIXME: is_di_on */
if (is_di_post_mode(vf)) {
/* check mif enable status, disable post di */
cur_dev->rdma_func[vpp_index].rdma_wr(DI_POST_CTRL, 0x3 << 30);
cur_dev->rdma_func[vpp_index].rdma_wr
(DI_POST_SIZE,
(32 - 1) | ((128 - 1) << 16));
cur_dev->rdma_func[vpp_index].rdma_wr
(DI_IF1_GEN_REG,
READ_VCBUS_REG(DI_IF1_GEN_REG) &
0xfffffffe);
}
#endif
}
if (last_process_3d_type != process_3d_type ||
last_el_status != vf_with_el)
force_toggle = true;
if (!layer->dispbuf ||
(vf->type & VIDTYPE_COMPRESS &&
(layer->dispbuf->compWidth != vf->compWidth ||
layer->dispbuf->compHeight != vf->compHeight)) ||
(layer->dispbuf->width != vf->width ||
layer->dispbuf->height != vf->height)) {
video_prop_status |= VIDEO_PROP_CHANGE_SIZE;
if (debug_flag & DEBUG_FLAG_TRACE_EVENT)
pr_info("VD1 src size changed: %dx%x->%dx%d. cur:%p, new:%p\n",
layer->dispbuf ? layer->dispbuf->width : 0,
layer->dispbuf ? layer->dispbuf->height : 0,
vf->width, vf->height,
layer->dispbuf, vf);
}
/* switch buffer */
post_canvas = vf->canvas0Addr;
ret = layer_swap_frame
(vf, layer, force_toggle, vinfo);
if (ret >= vppfilter_success) {
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(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN)
amlog_mask
(LOG_MASK_FRAMEINFO,
"%s trans_fmt=%u\n", __func__, vf->trans_fmt);
#endif
}
if (ret == vppfilter_changed_but_hold) {
video_notify_flag |=
VIDEO_NOTIFY_NEED_NO_COMP;
vpp_hold_setting_cnt++;
if (layer->global_debug & DEBUG_FLAG_BASIC_INFO)
pr_info("toggle_frame vpp hold setting cnt: %d\n",
vpp_hold_setting_cnt);
} else {/* apply new vpp settings */
if (layer->next_frame_par->vscale_skip_count <= 1 &&
vf->type_original & VIDTYPE_SUPPORT_COMPRESS &&
!(vf->type_original & VIDTYPE_COMPRESS)) {
video_notify_flag |=
VIDEO_NOTIFY_NEED_NO_COMP;
if (layer->global_debug & DEBUG_FLAG_BASIC_INFO)
pr_info("disable no compress mode\n");
}
vpp_hold_setting_cnt = 0;
}
last_process_3d_type = process_3d_type;
/* if el is unnecessary, afbc2 need to be closed */
if (last_el_status == 1 && vf_with_el == 0)
need_disable_vd2 = true;
last_el_status = vf_with_el;
if (((vf->type & VIDTYPE_MVC) == 0) && last_mvc_status)
need_disable_vd2 = true;
if (vf->type & VIDTYPE_MVC)
last_mvc_status = true;
else
last_mvc_status = false;
/* FIXME: free correct keep frame */
if (!is_local_vf(layer->dispbuf) && !layer->do_switch) {
if (layer->keep_frame_id == 1)
video_pip_keeper_new_frame_notify();
else if (layer->keep_frame_id == 0)
video_keeper_new_frame_notify();
}
fgrain_update_table(layer, vf);
if (stop_update)
layer->new_vpp_setting = false;
ATRACE_COUNTER(__func__, 0);
}
static s32 primary_render_frame(struct video_layer_s *layer)
{
struct vpp_frame_par_s *frame_par;
bool force_setting = false;
u32 zoom_start_y, zoom_end_y, blank = 0;
struct scaler_setting_s local_vd2_pps;
struct blend_setting_s local_vd2_blend;
struct mif_pos_s local_vd2_mif;
bool update_vd2 = false;
struct vframe_s *dispbuf = NULL;
if (!layer)
return -1;
/* filter setting management */
if (layer->new_vpp_setting) {
layer->cur_frame_par = layer->next_frame_par;
cur_frame_par = layer->cur_frame_par;
}
if (glayer_info[layer->layer_id].fgrain_force_update) {
force_setting = true;
glayer_info[layer->layer_id].fgrain_force_update = false;
}
frame_par = layer->cur_frame_par;
if (layer->switch_vf && layer->vf_ext)
dispbuf = layer->vf_ext;
else
dispbuf = layer->dispbuf;
/* process cur frame for each vsync */
if (dispbuf) {
int need_afbc =
(dispbuf->type & VIDTYPE_COMPRESS);
int afbc_need_reset =
(layer->enabled && need_afbc &&
!is_afbc_enabled(layer->layer_id));
/*video on && afbc is off && is compress frame.*/
if (layer->new_vpp_setting || afbc_need_reset)
vd_set_dcu
(layer->layer_id, layer,
frame_par, dispbuf);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (cur_dispbuf2 &&
(layer->new_vpp_setting ||
afbc_need_reset ||
dvel_changed))
vd_set_dcu
(1, &vd_layer[1],
frame_par, cur_dispbuf2);
if (dvel_changed)
force_setting = true;
dvel_changed = false;
#endif
#ifdef TV_3D_FUNCTION_OPEN
if (last_mode_3d &&
(layer->new_vpp_setting ||
afbc_need_reset))
vd_set_dcu
(1, &vd_layer[1],
frame_par, dispbuf);
#endif
/* for vout change or interlace frame */
proc_vd_vsc_phase_per_vsync
(layer,
frame_par, dispbuf);
/* because 3d and dv process, vd2 need no scale. */
/* so don't call the vd2 proc_vd1_vsc_phase_per_vsync */
/* Do 3D process if enabled */
switch_3d_view_per_vsync(layer);
}
/* no frame parameter change */
if ((!layer->new_vpp_setting && !force_setting) || !frame_par) {
/* when new frame is toggled but video layer is not on */
/* need always flush pps register before pwr on */
/* to avoid pps coeff lost */
if (frame_par && dispbuf && !is_local_vf(dispbuf) &&
(!get_video_enabled() ||
get_video_onoff_state() ==
VIDEO_ENABLE_STATE_ON_PENDING))
vd_scaler_setting(layer, &layer->sc_setting);
/* dolby vision process for each vsync */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
dolby_vision_proc(layer, frame_par);
#endif
return 0;
}
/* VPP one time settings */
if (dispbuf) {
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
correct_vd1_mif_size_for_DV(frame_par, cur_dispbuf2);
#endif
/* progressive or decode interlace case height 1:1 */
/* vdin afbc and interlace case height 1:1 */
zoom_start_y = frame_par->VPP_vd_start_lines_;
zoom_end_y = frame_par->VPP_vd_end_lines_;
if ((dispbuf->type & VIDTYPE_INTERLACE) &&
(dispbuf->type & VIDTYPE_VIU_FIELD)) {
/* vdin interlace non afbc frame case height/2 */
zoom_start_y /= 2;
zoom_end_y = ((zoom_end_y + 1) >> 1) - 1;
} else if (dispbuf->type & VIDTYPE_MVC) {
/* mvc case, (height - blank)/2 */
if (framepacking_support)
blank = framepacking_blank;
else
blank = 0;
zoom_start_y /= 2;
zoom_end_y = ((zoom_end_y - blank + 1) >> 1) - 1;
}
layer->start_x_lines = frame_par->VPP_hd_start_lines_;
layer->end_x_lines = frame_par->VPP_hd_end_lines_;
layer->start_y_lines = zoom_start_y;
layer->end_y_lines = zoom_end_y;
config_vd_position
(layer, &layer->mif_setting);
config_aisr_position(layer, &layer->aisr_mif_setting);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_on() && cur_dispbuf2) {
config_dvel_position
(layer,
&local_vd2_mif,
cur_dispbuf2);
update_vd2 = true;
}
#endif
#ifdef TV_3D_FUNCTION_OPEN
if ((dispbuf->type & VIDTYPE_MVC) ||
last_mode_3d) {
config_3d_vd2_position
(layer, &local_vd2_mif);
update_vd2 = true;
}
#endif
if (layer->vd1_vd2_mux) {
layer->mif_setting.p_vd_mif_reg = &vd_layer[1].vd_mif_reg;
vd_mif_setting(&vd_layer[1], &layer->mif_setting);
} else {
vd_mif_setting(layer, &layer->mif_setting);
}
if (update_vd2)
vd_mif_setting(&vd_layer[1], &local_vd2_mif);
fgrain_config(layer,
layer->cur_frame_par,
&layer->mif_setting,
&layer->fgrain_setting,
dispbuf);
/* aisr mif setting */
aisr_reshape_cfg(layer, &layer->aisr_mif_setting);
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
/* work around to cut the last green line */
/* when two layer dv display and do vskip */
if (is_dolby_vision_on() &&
frame_par->vscale_skip_count > 0 &&
cur_dispbuf2 &&
frame_par->VPP_pic_in_height_ > 0)
frame_par->VPP_pic_in_height_--;
#endif
/* aisr pps config */
config_aisr_pps(layer, &layer->aisr_sc_setting);
config_vd_pps
(layer, &layer->sc_setting, vinfo);
config_vd_blend
(layer, &layer->bld_setting);
update_vd2 = false;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (for_dolby_vision_certification())
layer->sc_setting.sc_top_enable = false;
if (is_dolby_vision_on() && cur_dispbuf2) {
config_dvel_pps
(layer, &local_vd2_pps, vinfo);
config_dvel_blend
(layer, &local_vd2_blend, cur_dispbuf2);
update_vd2 = true;
}
#endif
#ifdef TV_3D_FUNCTION_OPEN
/*turn off vertical scaler when 3d display */
if ((dispbuf &&
(dispbuf->type & VIDTYPE_MVC)) ||
last_mode_3d) {
layer->sc_setting.sc_v_enable = false;
config_3d_vd2_pps
(layer, &local_vd2_pps, vinfo);
config_3d_vd2_blend
(layer, &local_vd2_blend);
update_vd2 = true;
}
#endif
vd_scaler_setting(layer, &layer->sc_setting);
aisr_scaler_setting(layer, &layer->aisr_sc_setting);
vd_blend_setting(layer, &layer->bld_setting);
if (update_vd2) {
vd_scaler_setting(&vd_layer[1], &local_vd2_pps);
vd_blend_setting(&vd_layer[1], &local_vd2_blend);
}
/* dolby vision process for each vsync */
/* need set after correct_vd1_mif_size_for_DV */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
dolby_vision_proc(layer, frame_par);
#endif
fgrain_setting(layer, &layer->fgrain_setting, dispbuf);
layer->new_vpp_setting = false;
return 1;
}
static int update_amvideo_recycle_buffer(void)
{
struct vframe_s *rdma_buf = NULL;
struct vframe_s *to_put_buf[DISPBUF_TO_PUT_MAX];
int i;
bool mismatch = true, need_force_recycle = true;
int put_cnt = 0;
memset(to_put_buf, 0, sizeof(to_put_buf));
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
/* after one vsync processing, should be same */
if (cur_rdma_buf != cur_dispbuf &&
cur_dispbuf != &vf_local) {
pr_err("expection: amvideo rdma_buf:%p, dispbuf:%p!\n",
cur_rdma_buf, cur_dispbuf);
return -1;
}
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
if (dispbuf_to_put[i] &&
IS_DI_POSTWRTIE(dispbuf_to_put[i]->type))
to_put_buf[put_cnt++] = dispbuf_to_put[i];
#endif
if (cur_dispbuf != &vf_local)
rdma_buf = cur_dispbuf;
if (rdma_buf &&
!IS_DI_POSTWRTIE(rdma_buf->type))
rdma_buf = NULL;
if (recycle_cnt[0] &&
(put_cnt > 0 || rdma_buf)) {
for (i = 0; i < recycle_cnt[0]; i++) {
if (recycle_buf[0][i] == rdma_buf)
need_force_recycle = false;
}
if (need_force_recycle)
return -EAGAIN;
pr_err("expection: normal amvideo recycle_cnt:%d, put_cnt:%d, recycle_buf:%p-%p, to_put:%p, rdma_buf:%p!\n",
recycle_cnt[0], put_cnt,
recycle_buf[0][0], recycle_buf[0][1],
to_put_buf[0], rdma_buf);
return -1;
}
if (!recycle_cnt[0]) {
for (i = 0; i < DISPBUF_TO_PUT_MAX + 1; i++)
recycle_buf[0][i] = NULL;
for (i = 0; i < put_cnt; i++) {
if (to_put_buf[i])
recycle_buf[0][recycle_cnt[0]++] =
to_put_buf[i];
if (rdma_buf && rdma_buf == to_put_buf[i])
mismatch = false;
}
if (rdma_buf && mismatch)
recycle_buf[0][recycle_cnt[0]++] = rdma_buf;
pr_debug("amvideo need recycle %d new buffers: %p, %p, %p, %p, put_cnt:%d, rdma_buf:%p\n",
recycle_cnt[0], recycle_buf[0][0], recycle_buf[0][1],
recycle_buf[0][2], recycle_buf[0][3],
put_cnt, rdma_buf);
} else {
pr_debug("amvideo need recycle %d remained buffers: %p, %p, %p, %p\n",
recycle_cnt[0], recycle_buf[0][0], recycle_buf[0][1],
recycle_buf[0][2], recycle_buf[0][3]);
}
return 0;
}
static int update_pip_recycle_buffer(void)
{
struct vframe_s *rdma_buf = NULL;
struct vframe_s *to_put_buf[DISPBUF_TO_PUT_MAX];
int i;
bool mismatch = true, need_force_recycle = true;
int put_cnt = 0;
memset(to_put_buf, 0, sizeof(to_put_buf));
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
/* after one vsync processing, should be same */
if (pip_rdma_buf != cur_pipbuf &&
cur_pipbuf != &local_pip) {
pr_err("expection: pip rdma_buf:%p, dispbuf:%p!\n",
pip_rdma_buf, cur_pipbuf);
return -1;
}
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
if (pipbuf_to_put[i] &&
IS_DI_POSTWRTIE(pipbuf_to_put[i]->type))
to_put_buf[put_cnt++] = pipbuf_to_put[i];
#endif
if (cur_pipbuf != &local_pip)
rdma_buf = cur_pipbuf;
if (rdma_buf &&
!IS_DI_POSTWRTIE(rdma_buf->type))
rdma_buf = NULL;
if (recycle_cnt[1] &&
(put_cnt > 0 || rdma_buf)) {
for (i = 0; i < recycle_cnt[1]; i++) {
if (recycle_buf[1][i] == rdma_buf)
need_force_recycle = false;
}
if (need_force_recycle)
return -EAGAIN;
pr_err("expection: pip recycle_cnt:%d, put_cnt:%d, recycle_buf:%p-%p, to_put:%p, rdma_buf:%p!\n",
recycle_cnt[1], put_cnt,
recycle_buf[1][0], recycle_buf[1][1],
to_put_buf[0], rdma_buf);
return -1;
}
if (!recycle_cnt[1]) {
for (i = 0; i < DISPBUF_TO_PUT_MAX + 1; i++)
recycle_buf[1][i] = NULL;
for (i = 0; i < put_cnt; i++) {
if (to_put_buf[i])
recycle_buf[1][recycle_cnt[1]++] =
to_put_buf[i];
if (rdma_buf && rdma_buf == to_put_buf[i])
mismatch = false;
}
if (rdma_buf && mismatch)
recycle_buf[1][recycle_cnt[1]++] = rdma_buf;
pr_debug("pip need recycle %d new buffers: %p, %p, %p, %p, put_cnt:%d, rdma_buf:%p\n",
recycle_cnt[1], recycle_buf[1][0], recycle_buf[1][1],
recycle_buf[1][2], recycle_buf[1][3],
put_cnt, rdma_buf);
} else {
pr_debug("pip need recycle %d remained buffers: %p, %p, %p, %p\n",
recycle_cnt[1], recycle_buf[1][0], recycle_buf[1][1],
recycle_buf[1][2], recycle_buf[1][3]);
}
return 0;
}
static int update_pip2_recycle_buffer(void)
{
struct vframe_s *rdma_buf = NULL;
struct vframe_s *to_put_buf[DISPBUF_TO_PUT_MAX];
int i;
bool mismatch = true, need_force_recycle = true;
int put_cnt = 0;
memset(to_put_buf, 0, sizeof(to_put_buf));
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
/* after one vsync processing, should be same */
if (pip2_rdma_buf != cur_pipbuf2 &&
cur_pipbuf2 != &local_pip2) {
pr_err("expection: pip2 rdma_buf:%p, dispbuf2:%p!\n",
pip2_rdma_buf, cur_pipbuf2);
return -1;
}
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
if (pipbuf2_to_put[i] &&
IS_DI_POSTWRTIE(pipbuf2_to_put[i]->type))
to_put_buf[put_cnt++] = pipbuf2_to_put[i];
#endif
if (cur_pipbuf2 != &local_pip2)
rdma_buf = cur_pipbuf2;
if (rdma_buf &&
!IS_DI_POSTWRTIE(rdma_buf->type))
rdma_buf = NULL;
if (recycle_cnt[2] &&
(put_cnt > 0 || rdma_buf)) {
for (i = 0; i < recycle_cnt[2]; i++) {
if (recycle_buf[2][i] == rdma_buf)
need_force_recycle = false;
}
if (need_force_recycle)
return -EAGAIN;
pr_err("expection: pip2 recycle_cnt:%d, put_cnt:%d, recycle_buf:%p-%p, to_put:%p, rdma_buf:%p!\n",
recycle_cnt[2], put_cnt,
recycle_buf[2][0], recycle_buf[2][1],
to_put_buf[0], rdma_buf);
return -1;
}
if (!recycle_cnt[2]) {
for (i = 0; i < DISPBUF_TO_PUT_MAX + 1; i++)
recycle_buf[2][i] = NULL;
for (i = 0; i < put_cnt; i++) {
if (to_put_buf[i])
recycle_buf[2][recycle_cnt[2]++] =
to_put_buf[i];
if (rdma_buf && rdma_buf == to_put_buf[i])
mismatch = false;
}
if (rdma_buf && mismatch)
recycle_buf[2][recycle_cnt[2]++] = rdma_buf;
pr_debug("pip2 need recycle %d new buffers: %p, %p, %p, %p, put_cnt:%d, rdma_buf:%p\n",
recycle_cnt[2], recycle_buf[2][0], recycle_buf[2][1],
recycle_buf[2][2], recycle_buf[2][3],
put_cnt, rdma_buf);
} else {
pr_debug("pip2 need recycle %d remained buffers: %p, %p, %p, %p\n",
recycle_cnt[2], recycle_buf[2][0], recycle_buf[2][1],
recycle_buf[2][2], recycle_buf[2][3]);
}
return 0;
}
void set_alpha_scpxn(struct video_layer_s *layer,
struct componser_info_t *componser_info)
{
struct pip_alpha_scpxn_s alpha_win;
int win_num = 0;
int win_en = 0;
int i;
memset(&alpha_win, 0, sizeof(struct pip_alpha_scpxn_s));
if (componser_info)
win_num = componser_info->count;
for (i = 0; i < win_num; i++) {
alpha_win.scpxn_bgn_h[i] = componser_info->axis[i][0];
alpha_win.scpxn_end_h[i] = componser_info->axis[i][2];
alpha_win.scpxn_bgn_v[i] = componser_info->axis[i][1];
alpha_win.scpxn_end_v[i] = componser_info->axis[i][3];
win_en |= 1 << i;
}
set_alpha(layer, win_en, &alpha_win);
}
static void blend_reg_conflict_detect(void)
{
u32 r1, r2, r3;
u32 blend_en = 0;
if (!legacy_vpp) {
r1 = READ_VCBUS_REG(VD1_BLEND_SRC_CTRL);
if (r1 & 0xfff)
blend_en = 1;
} else {
r1 = READ_VCBUS_REG(VPP_MISC);
if (r1 & VPP_VD1_POSTBLEND)
blend_en = 1;
}
r2 = READ_VCBUS_REG(vd_layer[0].vd_afbc_reg.afbc_enable);
r3 = READ_VCBUS_REG(vd_layer[0].vd_mif_reg.vd_if0_gen_reg);
if (r2 == 0 && r3 == 0 && blend_en)
blend_conflict_cnt++;
blend_en = 0;
if (!legacy_vpp) {
r1 = READ_VCBUS_REG(VD2_BLEND_SRC_CTRL);
if (r1 & 0xfff)
blend_en = 1;
} else {
r1 = READ_VCBUS_REG(VPP_MISC);
if (r1 & VPP_VD2_POSTBLEND)
blend_en = 1;
}
r2 = READ_VCBUS_REG(vd_layer[1].vd_afbc_reg.afbc_enable);
r3 = READ_VCBUS_REG(vd_layer[1].vd_mif_reg.vd_if0_gen_reg);
if (r2 == 0 && r3 == 0 && blend_en)
blend_conflict_cnt++;
blend_en = 0;
if (cur_dev->max_vd_layers == 3) {
r1 = READ_VCBUS_REG(VD3_BLEND_SRC_CTRL);
if (r1 & 0xfff)
blend_en = 1;
r2 = READ_VCBUS_REG(vd_layer[2].vd_afbc_reg.afbc_enable);
r3 = READ_VCBUS_REG(vd_layer[2].vd_mif_reg.vd_if0_gen_reg);
if (r2 == 0 && r3 == 0 && blend_en)
blend_conflict_cnt++;
}
}
static int ai_pq_disable;
static int ai_pq_debug;
static int ai_pq_value = -1;
static int ai_pq_policy = 1;
#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 vout_type;
struct vframe_s *vf;
struct vframe_s *vf_tmp;
bool show_nosync = false;
int toggle_cnt;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
struct vframe_s *dv_new_vf = NULL;
#endif
struct vframe_s *path0_new_frame = NULL;
struct vframe_s *path1_new_frame = NULL;
struct vframe_s *path2_new_frame = NULL;
struct vframe_s *path3_new_frame = NULL;
struct vframe_s *path4_new_frame = NULL;
struct vframe_s *path5_new_frame = NULL;
struct vframe_s *new_frame = NULL;
struct vframe_s *new_frame2 = NULL;
struct vframe_s *new_frame3 = NULL;
struct vframe_s *cur_dispbuf_back = cur_dispbuf;
struct vframe_s *di_post_vf = NULL;
bool di_post_process_done = false;
u32 cur_blackout;
static u32 interrupt_count;
static s32 cur_vd1_path_id = VFM_PATH_INVALID;
static s32 cur_vd2_path_id = VFM_PATH_INVALID;
static s32 cur_vd3_path_id = VFM_PATH_INVALID;
u32 next_afbc_request = atomic_read(&gafbc_request);
s32 vd1_path_id = glayer_info[0].display_path_id;
s32 vd2_path_id = glayer_info[1].display_path_id;
s32 vd3_path_id = glayer_info[2].display_path_id;
int axis[4];
int crop[4];
int pq_process_debug[4];
enum vframe_signal_fmt_e fmt;
int i, j = 0;
int source_type = 0;
blend_reg_conflict_detect();
if (vd_layer[0].force_disable)
atomic_set(&vt_disable_video_done, 1);
if (video_suspend && video_suspend_cycle >= 1) {
if (log_out)
pr_info("video suspend, vsync exit\n");
log_out = 0;
return IRQ_HANDLED;
}
if (debug_flag & DEBUG_FLAG_VSYNC_DONONE)
return IRQ_HANDLED;
#ifdef CONFIG_AMLOGIC_MEDIA_MSYNC
msync_vsync_update();
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_on())
dolby_vision_update_backlight();
#endif
if (cur_vd1_path_id == 0xff)
cur_vd1_path_id = vd1_path_id;
if (cur_vd2_path_id == 0xff)
cur_vd2_path_id = vd2_path_id;
if (cur_vd3_path_id == 0xff)
cur_vd3_path_id = vd3_path_id;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
/* Just a workaround to enable RDMA without any register config.
* Becasuse rdma is enabled after first rdma config.
* Previously, it will write register directly and
* maybe out of blanking in first irq.
*/
if (first_irq) {
first_irq = false;
goto RUN_FIRST_RDMA;
}
#endif
vout_type = detect_vout_type(vinfo);
/* hold_line = calc_hold_line(); */
get_count = 0;
get_count_pip = 0;
get_count_pip2 = 0;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
/* karry ?*/
glayer_info[0].need_no_compress =
(next_afbc_request & (i + 1)) ? true : false;
vd_layer[i].bypass_pps = bypass_pps;
vd_layer[i].global_debug = debug_flag;
vd_layer[i].vout_type = vout_type;
}
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_AMLOGIC_VIDEO_COMPOSER
vsync_notify_video_composer();
#endif
#ifdef CONFIG_AMLOGIC_VIDEOQUEUE
vsync_notify_videoqueue();
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()) {
char *provider_name = NULL;
if (vd1_path_id == VFM_PATH_PIP) {
provider_name = vf_get_provider_name(RECEIVERPIP_NAME);
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name)
dolby_vision_set_provider(provider_name);
else
dolby_vision_set_provider(dv_provider);
} else {
provider_name = vf_get_provider_name(RECEIVER_NAME);
while (provider_name) {
if (!vf_get_provider_name(provider_name))
break;
provider_name =
vf_get_provider_name(provider_name);
}
if (provider_name)
dolby_vision_set_provider(provider_name);
else
dolby_vision_set_provider(dv_provider);
}
}
if (is_dolby_vision_enable() && dovi_drop_flag) {
struct vframe_s *vf = NULL;
unsigned int cnt = 10;
int max_drop_index;
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("dovi_drop_frame_num %d, omx_run %d\n",
dovi_drop_frame_num, omx_run);
while (cnt--) {
vf = video_vf_peek();
if (vf && is_dovi_frame(vf)) {
max_drop_index = omx_run ?
omx_need_drop_frame_num : dovi_drop_frame_num;
if (max_drop_index >= vf->omx_index) {
if (dolby_vision_drop_frame() == 1)
break;
continue;
} else if (omx_run &&
(vf->omx_index >
omx_need_drop_frame_num)) {
/* all drop done*/
dovi_drop_flag = false;
omx_drop_done = true;
if (debug_flag &
DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("dolby vision drop done\n");
break;
}
break;
}
break;
}
}
#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)) {
break;
}
#endif
if (!vf)
break;
if (omx_need_drop_frame_num >= vf->omx_index) {
vf = video_vf_get();
if (video_vf_put(vf) < 0)
check_dispbuf(vf, true);
video_drop_vf_cnt++;
if (debug_flag & DEBUG_FLAG_PRINT_DROP_FRAME)
pr_info("drop frame: drop count %d\n",
video_drop_vf_cnt);
} else {
omx_drop_done = true;
break;
}
}
}
vf = video_vf_peek();
if (!vf)
vf_tmp = cur_dispbuf;
else
vf_tmp = vf;
if (vf_tmp) {
if (glayer_info[0].display_path_id == VFM_PATH_AUTO) {
if (vf_tmp->sidebind_type
== glayer_info[0].sideband_type ||
vf_tmp->sidebind_type == 0) {
pr_info("VID: path_id %d -> %d\n",
glayer_info[0].display_path_id,
VFM_PATH_AMVIDEO);
glayer_info[0].display_path_id =
VFM_PATH_AMVIDEO;
vd1_path_id = glayer_info[0].display_path_id;
} else if (glayer_info[0].sideband_type != -1)
pr_info("vf->sideband_type =%d,layertype=%d\n",
vf_tmp->sidebind_type,
glayer_info[0].sideband_type);
}
}
/* vout mode detection under old tunnel mode */
if ((vf) && ((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0)) {
if (strcmp(old_vmode, new_vmode)) {
vd_layer[0].property_changed = true;
vd_layer[1].property_changed = true;
vd_layer[2].property_changed = true;
pr_info("detect vout mode change!!!!!!!!!!!!\n");
strcpy(old_vmode, new_vmode);
}
}
toggle_cnt = 0;
vsync_count++;
timer_count++;
/*the first/second vf di maybe bypass, So we need to calculate the
*first three frames
*/
if (display_frame_count < 3 && vf &&
(vf->source_type == VFRAME_SOURCE_TYPE_HDMI ||
vf->source_type == VFRAME_SOURCE_TYPE_CVBS ||
vf->source_type == VFRAME_SOURCE_TYPE_TUNER))
hdmi_in_delay_maxmin_old(vf);
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
if (cur_frame_par &&
vd1_path_id == VFM_PATH_AMVIDEO) {
/*need call every vsync*/
if (vf)
vlock_process(vf, cur_frame_par);
else
vlock_process(NULL, cur_frame_par);
}
#endif
enc_line = get_cur_enc_line();
if (enc_line > vsync_enter_line_max)
vsync_enter_line_max = enc_line;
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
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 ? vf : cur_dispbuf;
if (chk_vf)
force_adjust =
((chk_vf->type & VIDTYPE_VIU_444) ||
(chk_vf->type & VIDTYPE_RGB_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);
}
}
#endif
#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 (vd_layer[0].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 &&
(vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF ||
vd1_path_id == VFM_PATH_AUTO)) {
dolby_vision_check_mvc(vf);
dolby_vision_check_hdr10(vf);
dolby_vision_check_hdr10plus(vf);
dolby_vision_check_hlg(vf);
}
#endif
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);
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
videosync_pcrscr_inc(vsync_pts_inc_adj);
#endif
} else {
timestamp_pcrscr_inc(vsync_pts_inc + 1);
timestamp_apts_inc(vsync_pts_inc + 1);
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
videosync_pcrscr_inc(vsync_pts_inc + 1);
#endif
}
} 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);
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
videosync_pcrscr_update(vsync_pts_inc_scale,
vsync_pts_inc_scale_base);
#endif
#ifdef CONFIG_AMLOGIC_VIDEOQUEUE
videoqueue_pcrscr_update(vsync_pts_inc_scale,
vsync_pts_inc_scale_base);
#endif
} else if (vsync_slow_factor > 1000) {
u32 inc = (vsync_slow_factor / 1000)
* vsync_pts_inc / 1000;
timestamp_pcrscr_inc(inc);
timestamp_apts_inc(inc);
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
videosync_pcrscr_inc(inc);
#endif
} else {
timestamp_pcrscr_inc(vsync_pts_inc / vsync_slow_factor);
timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor);
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
videosync_pcrscr_inc(vsync_pts_inc / vsync_slow_factor);
#endif
}
}
if (omx_secret_mode) {
u32 system_time = timestamp_pcrscr_get();
int diff = 0;
unsigned long delta1 = 0;
unsigned long time_setomxpts_delta = 0;
diff = system_time - omx_pts;
if (time_setomxpts > 0 && time_setomxpts_last > 0) {
/* 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 */
delta1 = func_div(sched_clock() - time_setomxpts, 1000);
time_setomxpts_delta = func_div(time_setomxpts -
time_setomxpts_last, 1000);
if ((time_setomxpts_delta >
((ulong)(4 * vsync_pts_inc) * 1000 / 90)) ||
((diff - omx_pts_interval_upper * 3 / 2) > 0) ||
((diff - omx_pts_interval_lower * 3 / 2)
< 0)) {
time_setomxpts = 0;
time_setomxpts_last = 0;
if (debug_flag & DEBUG_FLAG_PTS_TRACE)
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) &&
video_start_post) {
timestamp_pcrscr_enable(1);
if (debug_flag & DEBUG_FLAG_PTS_TRACE)
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*/
if (debug_flag & DEBUG_FLAG_OMX_DEBUG_DROP_FRAME) {
pr_info("pcrscr_set sys_time=%d, omx_pts=%d, diff=%d",
system_time, omx_pts, diff);
}
timestamp_pcrscr_set(omx_pts + DURATION_GCD);
} else if (((diff - omx_pts_interval_upper / 2) > 0 ||
(diff - omx_pts_interval_lower / 2) < 0) &&
(omx_pts_set_from_hwc_count_begin <
OMX_MAX_COUNT_RESET_SYSTEMTIME_BEGIN) &&
video_start_post) {
timestamp_pcrscr_enable(1);
if (debug_flag & DEBUG_FLAG_PTS_TRACE)
pr_info("begin-system_time=%d, omx_pts=%d, diff=%d\n",
system_time, omx_pts, diff);
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) &&
video_start_post) {
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;
for (i = 0; i < cur_dev->max_vd_layers; i++) {
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
struct vframe_s *_cur_dispbuf;
struct vframe_s *_local_vf;
switch (i) {
case 0:
_cur_dispbuf = cur_dispbuf;
_local_vf = &vf_local;
break;
case 1:
_cur_dispbuf = cur_pipbuf;
_local_vf = &local_pip;
break;
case 2:
_cur_dispbuf = cur_pipbuf2;
_local_vf = &local_pip2;
break;
}
if (recycle_cnt[i] > 0 && _cur_dispbuf != _local_vf) {
for (j = 0; j < recycle_cnt[i]; j++) {
if ((recycle_buf[i][j] &&
_cur_dispbuf != recycle_buf[i][j]) &&
(recycle_buf[i][j]->flag & VFRAME_FLAG_DI_PW_VFM)) {
if (i == 0)
di_release_count++;
dim_post_keep_cmd_release2(recycle_buf[i][j]);
} else if (recycle_buf[i][j] &&
_cur_dispbuf == recycle_buf[i][j]) {
pr_err("recycle %d di buffer conflict, recycle vf:%p\n",
i, recycle_buf[i][j]);
}
recycle_buf[i][j] = NULL;
}
recycle_cnt[i] = 0;
}
#endif
if (vd_layer[i].dispbuf_mapping == &cur_dispbuf &&
(cur_dispbuf == &vf_local ||
!cur_dispbuf) &&
vd_layer[i].dispbuf != cur_dispbuf)
vd_layer[i].dispbuf = cur_dispbuf;
if (vd_layer[i].dispbuf_mapping == &cur_pipbuf &&
(cur_pipbuf == &local_pip ||
!cur_pipbuf) &&
vd_layer[i].dispbuf != cur_pipbuf)
vd_layer[i].dispbuf = cur_pipbuf;
if (vd_layer[i].dispbuf_mapping == &cur_pipbuf2 &&
(cur_pipbuf2 == &local_pip2 ||
!cur_pipbuf2) &&
vd_layer[i].dispbuf != cur_pipbuf2)
vd_layer[i].dispbuf = cur_pipbuf2;
if (gvideo_recv[0] &&
vd_layer[i].dispbuf_mapping == &gvideo_recv[0]->cur_buf &&
(gvideo_recv[0]->cur_buf == &gvideo_recv[0]->local_buf ||
!gvideo_recv[0]->cur_buf) &&
vd_layer[i].dispbuf != gvideo_recv[0]->cur_buf)
vd_layer[i].dispbuf = gvideo_recv[0]->cur_buf;
if (gvideo_recv[1] &&
vd_layer[i].dispbuf_mapping == &gvideo_recv[1]->cur_buf &&
(gvideo_recv[1]->cur_buf == &gvideo_recv[1]->local_buf ||
!gvideo_recv[1]->cur_buf) &&
vd_layer[i].dispbuf != gvideo_recv[1]->cur_buf)
vd_layer[i].dispbuf = gvideo_recv[1]->cur_buf;
if (gvideo_recv[2] &&
vd_layer[i].dispbuf_mapping == &gvideo_recv[2]->cur_buf &&
(gvideo_recv[2]->cur_buf == &gvideo_recv[2]->local_buf ||
!gvideo_recv[2]->cur_buf) &&
vd_layer[i].dispbuf != gvideo_recv[2]->cur_buf)
vd_layer[i].dispbuf = gvideo_recv[2]->cur_buf;
}
if (atomic_read(&video_pause_flag) &&
!(vd_layer[0].global_output == 1 &&
vd_layer[0].enabled != vd_layer[0].enabled_status_saved))
goto exit;
fmt = (enum vframe_signal_fmt_e)atomic_read(&primary_src_fmt);
if (fmt != atomic_read(&cur_primary_src_fmt)) {
if (debug_flag & DEBUG_FLAG_TRACE_EVENT) {
char *old_str = NULL, *new_str = NULL;
enum vframe_signal_fmt_e old_fmt;
old_fmt = (enum vframe_signal_fmt_e)
atomic_read(&cur_primary_src_fmt);
if (old_fmt != VFRAME_SIGNAL_FMT_INVALID)
old_str = (char *)src_fmt_str[old_fmt];
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
new_str = (char *)src_fmt_str[fmt];
pr_info("VD1 src fmt changed: %s->%s.\n",
old_str ? old_str : "invalid",
new_str ? new_str : "invalid");
}
atomic_set(&cur_primary_src_fmt, fmt);
video_prop_status |= VIDEO_PROP_CHANGE_FMT;
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_vsync_rdma_enable()) {
vd_layer[0].cur_canvas_id = vd_layer[0].next_canvas_id;
vd_layer[1].cur_canvas_id = vd_layer[1].next_canvas_id;
vd_layer[2].cur_canvas_id = vd_layer[2].next_canvas_id;
} else {
if (rdma_enable_pre)
goto exit;
vd_layer[0].cur_canvas_id = 0;
vd_layer[0].next_canvas_id = 1;
vd_layer[1].cur_canvas_id = 0;
vd_layer[1].next_canvas_id = 1;
vd_layer[2].cur_canvas_id = 0;
vd_layer[2].next_canvas_id = 1;
}
if (!over_sync) {
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (dispbuf_to_put[i]) {
dispbuf_to_put[i]->rendered = true;
if (!video_vf_put(dispbuf_to_put[i])) {
dispbuf_to_put[i] = NULL;
dispbuf_to_put_num--;
}
}
}
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (pipbuf_to_put[i]) {
pipbuf_to_put[i]->rendered = true;
if (!pip_vf_put(pipbuf_to_put[i])) {
pipbuf_to_put[i] = NULL;
pipbuf_to_put_num--;
}
}
}
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) {
if (pipbuf2_to_put[i]) {
pipbuf2_to_put[i]->rendered = true;
if (!pip2_vf_put(pipbuf2_to_put[i])) {
pipbuf2_to_put[i] = NULL;
pipbuf2_to_put_num--;
}
}
}
}
#endif
if (gvideo_recv[0])
gvideo_recv[0]->func->early_proc(gvideo_recv[0],
over_sync ? 1 : 0);
if (gvideo_recv[1])
gvideo_recv[1]->func->early_proc(gvideo_recv[1],
over_sync ? 1 : 0);
if (gvideo_recv[2])
gvideo_recv[2]->func->early_proc(gvideo_recv[2],
over_sync ? 1 : 0);
over_sync = false;
if (!cur_dispbuf || cur_dispbuf == &vf_local) {
vf = video_vf_peek();
if (vf) {
if (hdmi_in_onvideo == 0) {
if (!nopostvideostart)
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 {
goto SET_FILTER;
}
}
vf = video_vf_peek();
/*process hdmi in video sync*/
if (vf) {
/*step 1: audio required*/
if (hdmin_delay_start > 0) {
process_hdmi_video_sync(vf);
hdmin_delay_start = 0;
hdmi_vframe_count = 0;
}
/*step 2: recheck video sync after hdmi-in start*/
if (hdmi_delay_first_check) {
hdmi_vframe_count++;
if (hdmi_vframe_count > HDMI_DELAY_FIRST_CHECK_COUNT) {
process_hdmi_video_sync(vf);
hdmi_vframe_count = 0;
hdmi_delay_first_check = false;
}
/*step 3: re-check video sync every 5s by n times */
} else if (hdmi_delay_normal_check) {
hdmi_vframe_count++;
if (hdmi_vframe_count > HDMI_DELAY_NORMAL_CHECK_COUNT) {
process_hdmi_video_sync(vf);
hdmi_vframe_count = 0;
}
}
/* HDMI-IN AV SYNC Control, delay video*/
if (!hdmin_delay_done) {
if (hdmi_in_delay_check(vf) > 0)
goto exit;
}
/*HDMI-IN AV SYNC Control, drop video*/
if (hdmin_need_drop_count > 0)
hdmi_in_drop_frame();
}
/* buffer switch management */
vf = video_vf_peek();
/*debug info for skip & repeate vframe case*/
if (!vf) {
underflow++;
/* video master mode, reduce pcrscr */
if (tsync_get_mode() == TSYNC_MODE_VMASTER) {
s32 pts_inc = 0 - vsync_pts_inc;
timestamp_pcrscr_inc(pts_inc);
}
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;
/* toggle_3d_fa_frame*/
/* determine the out frame is L or R or blank */
judge_3d_fa_out_mode();
while (vf && !video_suspend) {
if (debug_flag & DEBUG_FLAG_OMX_DEBUG_DROP_FRAME) {
pr_info("next pts= %d,index %d,pcr = %d,vpts = %d\n",
vf->pts, vf->omx_index,
timestamp_pcrscr_get(), timestamp_vpts_get());
}
if ((omx_continuous_drop_flag && omx_run) &&
!(debug_flag & DEBUG_FLAG_OMX_DISABLE_DROP_FRAME)) {
if (is_dolby_vision_enable() && vf &&
is_dovi_frame(vf)) {
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("dovi ignore continuous drop\n");
/* if (omx_run)
* dolby_vision_drop_frame();
*/
} else {
if (debug_flag &
DEBUG_FLAG_OMX_DEBUG_DROP_FRAME) {
pr_info("drop omx_index %d, pts %d\n",
vf->omx_index, vf->pts);
}
vf = vf_get(RECEIVER_NAME);
if (vf) {
vf_put(vf, RECEIVER_NAME);
video_drop_vf_cnt++;
if (debug_flag &
DEBUG_FLAG_PRINT_DROP_FRAME)
pr_info("drop frame: drop count %d\n",
video_drop_vf_cnt);
}
vf = video_vf_peek();
continue;
}
}
if (vpts_expire(cur_dispbuf, vf, toggle_cnt) || show_nosync) {
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
int iret1 = 0, iret2 = 0, iret3 = 0;
#endif
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);
if (pts_trace > 4)
pr_info("smooth trace:%d\n", pts_trace);
}
amlog_mask_if(toggle_cnt > 0, LOG_MASK_FRAMESKIP,
"skipped\n");
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if ((vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF ||
vd1_path_id == VFM_PATH_AUTO) &&
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))
break;
frame_skip_check_cnt = 0;
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
if (vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF)
iret1 = amvecm_on_vs
((cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
if (vd2_path_id == VFM_PATH_AMVIDEO)
iret2 = amvecm_on_vs
((cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
if (vd3_path_id == VFM_PATH_AMVIDEO)
iret3 = amvecm_on_vs
((cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
if (iret1 == 1 || iret2 == 1 || iret3 == 1)
break;
#endif
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)) {
vdin_frame_skip_cnt++;
break;
}
force_blackout = 0;
if (vf) {
if (last_mode_3d !=
vf->mode_3d_enable) {
last_mode_3d =
vf->mode_3d_enable;
}
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN
video_3d_format = vf->trans_fmt;
#endif
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
/*check metadata crc*/
if (vf &&
(vf->source_type == VFRAME_SOURCE_TYPE_HDMI ||
vf->source_type == VFRAME_SOURCE_TYPE_CVBS) &&
dv_vf_crc_check(vf)) {
break; // not render err crc frame
}
#endif
path0_new_frame = vsync_toggle_frame(vf, __LINE__);
/* The v4l2 capture needs a empty vframe to flush */
if (has_receive_dummy_vframe())
break;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF ||
vd1_path_id == VFM_PATH_AUTO)
dv_new_vf = dvel_toggle_frame(vf, true);
if (hold_video)
dv_new_vf = NULL;
#endif
if (trickmode_fffb == 1) {
trickmode_vpts = vf->pts;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
/* FIXME: replace is_di_on */
if (is_di_post_mode(vf)) {
atomic_set(&trickmode_framedone, 1);
video_notify_flag |=
VIDEO_NOTIFY_TRICK_WAIT;
} else {
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) {
if ((vf->flag & VFRAME_FLAG_VIDEO_COMPOSER) &&
(debug_flag &
DEBUG_FLAG_COMPOSER_NO_DROP_FRAME)) {
pr_info("composer not drop\n");
vf = NULL;
}
}
if (!vf)
next_peek_underflow++;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if ((vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF ||
vd1_path_id == VFM_PATH_AUTO) &&
for_dolby_vision_certification() &&
dv_new_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++;
if (debug_flag & DEBUG_FLAG_PRINT_DROP_FRAME)
pr_info("drop frame: drop count %d\n",
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()) {
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
int iret1 = 0, iret2 = 0, iret3 = 0;
#endif
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 ((vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF ||
vd1_path_id == VFM_PATH_AUTO) &&
dolby_vision_need_wait())
break;
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
if (vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF)
iret1 = amvecm_on_vs
((cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
if (vd2_path_id == VFM_PATH_AMVIDEO)
iret2 = amvecm_on_vs
((cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
/* karry ? */
if (vd3_path_id == VFM_PATH_AMVIDEO)
iret3 = amvecm_on_vs
((cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
if (iret1 == 1 || iret2 == 1 || iret3 == 1)
break;
#endif
vf = video_vf_get();
if (!vf) {
ATRACE_COUNTER(MODULE_NAME,
__LINE__);
break;
}
path0_new_frame = vsync_toggle_frame(vf, __LINE__);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF ||
vd1_path_id == VFM_PATH_AUTO)
dv_new_vf =
dvel_toggle_frame(vf, true);
if (hold_video)
dv_new_vf = NULL;
#endif
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);
}
}
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:
if (cur_dispbuf_back != cur_dispbuf) {
display_frame_count++;
drop_frame_count = receive_frame_count - display_frame_count;
}
vf = pip_vf_peek();
videopip_get_vf_cnt = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
/* check video frame before VECM process */
if (vd1_path_id == VFM_PATH_PIP && vf &&
is_dolby_vision_enable()) {
dolby_vision_check_hdr10(vf);
dolby_vision_check_hdr10plus(vf);
dolby_vision_check_hlg(vf);
}
#endif
while (vf && !video_suspend) {
if (!vf->frame_dirty) {
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
int iret1 = 0, iret2 = 0, iret3 = 0;
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vd1_path_id == VFM_PATH_PIP &&
dolby_vision_need_wait_pip())
break;
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
if (vd1_path_id == VFM_PATH_PIP)
iret1 = amvecm_on_vs
((cur_pipbuf != &local_pip)
? cur_pipbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
if (vd2_path_id == VFM_PATH_DEF ||
vd2_path_id == VFM_PATH_PIP)
iret2 = amvecm_on_vs
((cur_pipbuf != &local_pip)
? cur_pipbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
if (vd3_path_id == VFM_PATH_PIP)
iret3 = amvecm_on_vs
((cur_pipbuf != &local_pip)
? cur_pipbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
if (iret1 == 1 || iret2 == 1 || iret3 == 1)
break;
#endif
vf = pip_vf_get();
if (vf) {
videopip_get_vf_cnt++;
path1_new_frame = pip_toggle_frame(vf);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vd1_path_id == VFM_PATH_PIP)
dv_new_vf = dvel_toggle_frame(vf, true);
#endif
}
} else {
vf = pip_vf_get();
if (vf) {
videopip_get_vf_cnt++;
if (pip_vf_put(vf) < 0)
check_pipbuf(vf, true);
}
}
vf = pip_vf_peek();
}
/* vsync_notify_videosync(); */
if (videopip_get_vf_cnt >= 2) {
videopip_drop_vf_cnt += (videopip_get_vf_cnt - 1);
if (debug_flag & DEBUG_FLAG_PRINT_DROP_FRAME)
pr_info("videopip drop frame: drop count %d\n",
videopip_drop_vf_cnt);
}
vf = pip2_vf_peek();
videopip2_get_vf_cnt = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
/* check video frame before VECM process */
if (vd1_path_id == VFM_PATH_PIP2 && vf &&
is_dolby_vision_enable()) {
dolby_vision_check_hdr10(vf);
dolby_vision_check_hdr10plus(vf);
dolby_vision_check_hlg(vf);
}
#endif
while (vf && !video_suspend) {
if (!vf->frame_dirty) {
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
int iret1 = 0, iret2 = 0, iret3 = 0;
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vd1_path_id == VFM_PATH_PIP2 &&
dolby_vision_need_wait_pip2())
break;
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
if (vd1_path_id == VFM_PATH_PIP2)
iret1 = amvecm_on_vs
((cur_pipbuf2 != &local_pip2)
? cur_pipbuf2 : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
if (vd2_path_id == VFM_PATH_PIP2)
iret2 = amvecm_on_vs
((cur_pipbuf2 != &local_pip2)
? cur_pipbuf2 : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
if (vd3_path_id == VFM_PATH_DEF ||
vd3_path_id == VFM_PATH_PIP2)
iret3 = amvecm_on_vs
((cur_pipbuf2 != &local_pip2)
? cur_pipbuf2 : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
if (iret1 == 1 || iret2 == 1 || iret3 == 1)
break;
#endif
vf = pip2_vf_get();
if (vf) {
videopip2_get_vf_cnt++;
path2_new_frame = pip2_toggle_frame(vf);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vd1_path_id == VFM_PATH_PIP2)
dv_new_vf = dvel_toggle_frame(vf, true);
#endif
}
} else {
vf = pip2_vf_get();
if (vf) {
videopip2_get_vf_cnt++;
if (pip2_vf_put(vf) < 0)
check_pipbuf2(vf, true);
}
}
vf = pip2_vf_peek();
}
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
vsync_notify_videosync();
#endif
if (videopip2_get_vf_cnt >= 2) {
videopip2_drop_vf_cnt += (videopip2_get_vf_cnt - 1);
if (debug_flag & DEBUG_FLAG_PRINT_DROP_FRAME)
pr_info("videopip2 drop frame: drop count %d\n",
videopip2_drop_vf_cnt);
}
/* video_render.0 toggle frame */
if (gvideo_recv[0]) {
path3_new_frame =
gvideo_recv[0]->func->dequeue_frame(gvideo_recv[0]);
if (path3_new_frame &&
tvin_vf_is_keeped(path3_new_frame)) {
new_frame_count = 0;
} else if (path3_new_frame) {
new_frame_count = gvideo_recv[0]->frame_count;
hdmi_in_delay_maxmin_new(path3_new_frame);
} else if (gvideo_recv[0]->cur_buf) {
if (tvin_vf_is_keeped(gvideo_recv[0]->cur_buf))
new_frame_count = 0;
}
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
if (vd1_path_id == VFM_PATH_VIDEO_RENDER0 &&
cur_frame_par) {
/*need call every vsync*/
if (path3_new_frame)
vlock_process(path3_new_frame,
cur_frame_par);
else if (vd_layer[0].dispbuf)
vlock_process(vd_layer[0].dispbuf,
cur_frame_par);
else
vlock_process(NULL, cur_frame_par);
}
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
if (vd1_path_id == gvideo_recv[0]->path_id) {
amvecm_on_vs
((gvideo_recv[0]->cur_buf !=
&gvideo_recv[0]->local_buf)
? gvideo_recv[0]->cur_buf : NULL,
path3_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
}
if (vd2_path_id == gvideo_recv[0]->path_id)
amvecm_on_vs
((gvideo_recv[0]->cur_buf !=
&gvideo_recv[0]->local_buf)
? gvideo_recv[0]->cur_buf : NULL,
path3_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
if (vd3_path_id == gvideo_recv[0]->path_id)
amvecm_on_vs
((gvideo_recv[0]->cur_buf !=
&gvideo_recv[0]->local_buf)
? gvideo_recv[0]->cur_buf : NULL,
path3_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
#endif
}
/* video_render.1 toggle frame */
if (gvideo_recv[1]) {
path4_new_frame =
gvideo_recv[1]->func->dequeue_frame(gvideo_recv[1]);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
if (vd1_path_id == gvideo_recv[1]->path_id) {
amvecm_on_vs
((gvideo_recv[1]->cur_buf !=
&gvideo_recv[1]->local_buf)
? gvideo_recv[1]->cur_buf : NULL,
path4_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
}
if (vd2_path_id == gvideo_recv[1]->path_id)
amvecm_on_vs
((gvideo_recv[1]->cur_buf !=
&gvideo_recv[1]->local_buf)
? gvideo_recv[1]->cur_buf : NULL,
path4_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
if (vd3_path_id == gvideo_recv[1]->path_id)
amvecm_on_vs
((gvideo_recv[1]->cur_buf !=
&gvideo_recv[1]->local_buf)
? gvideo_recv[1]->cur_buf : NULL,
path4_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
#endif
}
/* video_render.2 toggle frame */
if (gvideo_recv[2]) {
path5_new_frame =
gvideo_recv[2]->func->dequeue_frame(gvideo_recv[2]);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
if (vd1_path_id == gvideo_recv[2]->path_id) {
amvecm_on_vs
((gvideo_recv[2]->cur_buf !=
&gvideo_recv[2]->local_buf)
? gvideo_recv[2]->cur_buf : NULL,
path5_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD1_PATH,
VPP_TOP0);
}
if (vd2_path_id == gvideo_recv[2]->path_id)
amvecm_on_vs
((gvideo_recv[2]->cur_buf !=
&gvideo_recv[2]->local_buf)
? gvideo_recv[2]->cur_buf : NULL,
path5_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD2_PATH,
VPP_TOP0);
if (vd3_path_id == gvideo_recv[2]->path_id)
amvecm_on_vs
((gvideo_recv[2]->cur_buf !=
&gvideo_recv[2]->local_buf)
? gvideo_recv[2]->cur_buf : NULL,
path5_new_frame,
CSC_FLAG_CHECK_OUTPUT,
0,
0,
0,
0,
0,
0,
VD3_PATH,
VPP_TOP0);
#endif
}
/* FIXME: if need enable for vd1 */
#ifdef CHECK_LATER
if (!vd_layer[0].global_output) {
cur_vd1_path_id = VFM_PATH_INVALID;
vd1_path_id = VFM_PATH_INVALID;
}
#endif
if (!vd_layer[1].global_output) {
cur_vd2_path_id = VFM_PATH_INVALID;
vd2_path_id = VFM_PATH_INVALID;
}
if (!vd_layer[2].global_output) {
cur_vd3_path_id = VFM_PATH_INVALID;
vd3_path_id = VFM_PATH_INVALID;
}
vd_layer[0].force_switch_mode = force_switch_vf_mode;
vd_layer[1].force_switch_mode = force_switch_vf_mode;
if (cur_dev->max_vd_layers == 3)
vd_layer[2].force_switch_mode = force_switch_vf_mode;
if ((cur_vd1_path_id != vd1_path_id ||
cur_vd2_path_id != vd2_path_id ||
cur_vd3_path_id != vd3_path_id) &&
(debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) {
pr_info("VID: === before path switch ===\n");
pr_info("VID: \tcur_path_id: %d, %d, %d;\nVID: \tnew_path_id: %d, %d, %d;\nVID: \ttoggle:%p, %p, %p %p, %p, %p\nVID: \tcur:%p, %p, %p, %p, %p, %p;\n",
cur_vd1_path_id, cur_vd2_path_id, cur_vd3_path_id,
vd1_path_id, vd2_path_id, vd3_path_id,
path0_new_frame, path1_new_frame,
path2_new_frame, path3_new_frame,
path4_new_frame, path4_new_frame,
cur_dispbuf, cur_pipbuf, cur_pipbuf2,
gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL,
gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL,
gvideo_recv[2] ? gvideo_recv[2]->cur_buf : NULL);
pr_info("VID: \tdispbuf:%p, %p, %p; \tvf_ext:%p, %p, %p;\nVID: \tlocal:%p, %p, %p, %p, %p, %p\n",
vd_layer[0].dispbuf, vd_layer[1].dispbuf, vd_layer[2].dispbuf,
vd_layer[0].vf_ext, vd_layer[1].vf_ext, vd_layer[2].vf_ext,
&vf_local, &local_pip, &local_pip2,
gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL,
gvideo_recv[2] ? &gvideo_recv[2]->local_buf : NULL);
pr_info("VID: \tblackout:%d %d, %d force:%d;\n",
blackout, blackout_pip, blackout_pip2, force_blackout);
}
if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC)
pr_info("VID: path id: %d, %d, %d; new_frame:%p, %p, %p, %p, %p, %p cur:%p, %p, %p, %p, %p, %p; vd dispbuf:%p, %p, %p; vf_ext:%p, %p, %p; local:%p, %p, %p, %p, %p, %p\n",
vd1_path_id, vd2_path_id, vd2_path_id,
path0_new_frame, path1_new_frame,
path2_new_frame, path3_new_frame,
path4_new_frame, path5_new_frame,
cur_dispbuf, cur_pipbuf, cur_pipbuf2,
gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL,
gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL,
gvideo_recv[2] ? gvideo_recv[2]->cur_buf : NULL,
vd_layer[0].dispbuf, vd_layer[1].dispbuf, vd_layer[2].dispbuf,
vd_layer[0].vf_ext, vd_layer[1].vf_ext, vd_layer[2].vf_ext,
&vf_local, &local_pip, &local_pip2,
gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL,
gvideo_recv[2] ? &gvideo_recv[2]->local_buf : NULL);
if (vd_layer[0].dispbuf_mapping == &cur_dispbuf &&
(cur_dispbuf == &vf_local ||
!cur_dispbuf) &&
vd_layer[0].dispbuf != cur_dispbuf)
vd_layer[0].dispbuf = cur_dispbuf;
if (vd_layer[0].dispbuf_mapping == &cur_pipbuf &&
(cur_pipbuf == &local_pip ||
!cur_pipbuf) &&
vd_layer[0].dispbuf != cur_pipbuf)
vd_layer[0].dispbuf = cur_pipbuf;
if (vd_layer[0].dispbuf_mapping == &cur_pipbuf2 &&
(cur_pipbuf2 == &local_pip2 ||
!cur_pipbuf2) &&
vd_layer[0].dispbuf != cur_pipbuf2)
vd_layer[0].dispbuf = cur_pipbuf2;
if (gvideo_recv[0] &&
vd_layer[0].dispbuf_mapping == &gvideo_recv[0]->cur_buf &&
(gvideo_recv[0]->cur_buf == &gvideo_recv[0]->local_buf ||
!gvideo_recv[0]->cur_buf) &&
vd_layer[0].dispbuf != gvideo_recv[0]->cur_buf)
vd_layer[0].dispbuf = gvideo_recv[0]->cur_buf;
if (gvideo_recv[1] &&
vd_layer[0].dispbuf_mapping == &gvideo_recv[1]->cur_buf &&
(gvideo_recv[1]->cur_buf == &gvideo_recv[1]->local_buf ||
!gvideo_recv[1]->cur_buf) &&
vd_layer[0].dispbuf != gvideo_recv[1]->cur_buf)
vd_layer[0].dispbuf = gvideo_recv[1]->cur_buf;
if (gvideo_recv[2] &&
vd_layer[0].dispbuf_mapping == &gvideo_recv[2]->cur_buf &&
(gvideo_recv[2]->cur_buf == &gvideo_recv[2]->local_buf ||
!gvideo_recv[2]->cur_buf) &&
vd_layer[0].dispbuf != gvideo_recv[2]->cur_buf)
vd_layer[0].dispbuf = gvideo_recv[2]->cur_buf;
if (vd_layer[0].switch_vf &&
vd_layer[0].dispbuf &&
vd_layer[0].dispbuf->vf_ext)
vd_layer[0].vf_ext =
(struct vframe_s *)vd_layer[0].dispbuf->vf_ext;
else
vd_layer[0].vf_ext = NULL;
/* vd1 config */
if (gvideo_recv[0] &&
gvideo_recv[0]->path_id == vd1_path_id) {
/* video_render.0 display on VD1 */
new_frame = path3_new_frame;
if (!new_frame) {
if (!gvideo_recv[0]->cur_buf) {
/* video_render.0 no frame in display */
if (cur_vd1_path_id != vd1_path_id)
safe_switch_videolayer(0, false, true);
vd_layer[0].dispbuf = NULL;
} else if (gvideo_recv[0]->cur_buf ==
&gvideo_recv[0]->local_buf) {
/* video_render.0 keep frame */
vd_layer[0].dispbuf = gvideo_recv[0]->cur_buf;
} else if (vd_layer[0].dispbuf
!= gvideo_recv[0]->cur_buf) {
/* video_render.0 has frame in display */
new_frame = gvideo_recv[0]->cur_buf;
}
}
if (new_frame || gvideo_recv[0]->cur_buf)
vd_layer[0].dispbuf_mapping = &gvideo_recv[0]->cur_buf;
cur_blackout = 1;
} else if (gvideo_recv[1] &&
(gvideo_recv[1]->path_id == vd1_path_id)) {
/* video_render.1 display on VD1 */
new_frame = path4_new_frame;
if (!new_frame) {
if (!gvideo_recv[1]->cur_buf) {
/* video_render.1 no frame in display */
if (cur_vd1_path_id != vd1_path_id)
safe_switch_videolayer(0, false, true);
vd_layer[0].dispbuf = NULL;
} else if (gvideo_recv[1]->cur_buf ==
&gvideo_recv[1]->local_buf) {
/* video_render.1 keep frame */
vd_layer[0].dispbuf = gvideo_recv[1]->cur_buf;
} else if (vd_layer[0].dispbuf
!= gvideo_recv[1]->cur_buf) {
/* video_render.1 has frame in display */
new_frame = gvideo_recv[1]->cur_buf;
}
}
if (new_frame || gvideo_recv[1]->cur_buf)
vd_layer[0].dispbuf_mapping = &gvideo_recv[1]->cur_buf;
cur_blackout = 1;
} else if (gvideo_recv[2] &&
(gvideo_recv[2]->path_id == vd1_path_id)) {
/* video_render.2 display on VD1 */
new_frame = path5_new_frame;
if (!new_frame) {
if (!gvideo_recv[2]->cur_buf) {
/* video_render.2 no frame in display */
if (cur_vd1_path_id != vd1_path_id)
safe_switch_videolayer(0, false, true);
vd_layer[0].dispbuf = NULL;
} else if (gvideo_recv[2]->cur_buf ==
&gvideo_recv[2]->local_buf) {
/* video_render.2 keep frame */
vd_layer[0].dispbuf = gvideo_recv[2]->cur_buf;
} else if (vd_layer[0].dispbuf
!= gvideo_recv[2]->cur_buf) {
/* video_render.2 has frame in display */
new_frame = gvideo_recv[2]->cur_buf;
}
}
if (new_frame || gvideo_recv[2]->cur_buf)
vd_layer[0].dispbuf_mapping = &gvideo_recv[2]->cur_buf;
cur_blackout = 1;
} else if (vd1_path_id == VFM_PATH_PIP2) {
/* pip2 display on VD1 */
new_frame = path2_new_frame;
if (!new_frame) {
if (!cur_pipbuf2) {
/* pip2 no frame in display */
if (cur_vd1_path_id != vd1_path_id)
safe_switch_videolayer(0, false, true);
vd_layer[0].dispbuf = NULL;
} else if (cur_pipbuf2 == &local_pip2) {
/* pip2 keep frame */
vd_layer[0].dispbuf = cur_pipbuf2;
} else if (vd_layer[0].dispbuf
!= cur_pipbuf2) {
/* pip2 has frame in display */
new_frame = cur_pipbuf2;
}
}
if (new_frame || cur_pipbuf2)
vd_layer[0].dispbuf_mapping = &cur_pipbuf2;
cur_blackout = blackout_pip2 | force_blackout;
} else if (vd1_path_id == VFM_PATH_PIP) {
/* pip display on VD1 */
new_frame = path1_new_frame;
if (!new_frame) {
if (!cur_pipbuf) {
/* pip no frame in display */
if (cur_vd1_path_id != vd1_path_id)
safe_switch_videolayer(0, false, true);
vd_layer[0].dispbuf = NULL;
} else if (cur_pipbuf == &local_pip) {
/* pip keep frame */
vd_layer[0].dispbuf = cur_pipbuf;
} else if (vd_layer[0].dispbuf
!= cur_pipbuf) {
/* pip has frame in display */
new_frame = cur_pipbuf;
}
}
if (new_frame || cur_pipbuf)
vd_layer[0].dispbuf_mapping = &cur_pipbuf;
cur_blackout = blackout_pip | force_blackout;
} else if ((vd1_path_id != VFM_PATH_INVALID) &&
(vd1_path_id != VFM_PATH_AUTO)) {
/* priamry display on VD1 */
new_frame = path0_new_frame;
if (!new_frame) {
if (!cur_dispbuf) {
/* priamry no frame in display */
if (cur_vd1_path_id != vd1_path_id)
safe_switch_videolayer(0, false, true);
vd_layer[0].dispbuf = NULL;
} else if (cur_dispbuf == &vf_local) {
/* priamry keep frame */
vd_layer[0].dispbuf = cur_dispbuf;
} else if (vd_layer[0].dispbuf
!= cur_dispbuf) {
/* primary has frame in display */
new_frame = cur_dispbuf;
}
}
if (new_frame || cur_dispbuf)
vd_layer[0].dispbuf_mapping = &cur_dispbuf;
cur_blackout = blackout | force_blackout;
} else if (vd1_path_id == VFM_PATH_AUTO) {
new_frame = path0_new_frame;
if (path3_new_frame &&
(path3_new_frame->flag & VFRAME_FLAG_FAKE_FRAME)) {
new_frame = path3_new_frame;
pr_info("vsync: auto path2 get a fake\n");
}
if (!new_frame) {
if (cur_dispbuf == &vf_local)
vd_layer[0].dispbuf = cur_dispbuf;
}
if (gvideo_recv[0]->cur_buf &&
gvideo_recv[0]->cur_buf->flag & VFRAME_FLAG_FAKE_FRAME)
vd_layer[0].dispbuf = gvideo_recv[0]->cur_buf;
if (new_frame || cur_dispbuf)
vd_layer[0].dispbuf_mapping = &cur_dispbuf;
cur_blackout = blackout | force_blackout;
} else {
cur_blackout = 1;
}
/* vout mode detection under new non-tunnel mode */
if (vd_layer[0].dispbuf || vd_layer[1].dispbuf ||
vd_layer[2].dispbuf) {
if (strcmp(old_vmode, new_vmode)) {
vd_layer[0].property_changed = true;
vd_layer[1].property_changed = true;
vd_layer[2].property_changed = true;
pr_info("detect vout mode change!!!!!!!!!!!!\n");
strcpy(old_vmode, new_vmode);
}
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable() && vd_layer[0].global_output) {
/* no new frame but path switched case, */
if (new_frame && !is_local_vf(new_frame) &&
(!path0_new_frame || new_frame != path0_new_frame) &&
(!path1_new_frame || new_frame != path1_new_frame) &&
(!path2_new_frame || new_frame != path2_new_frame) &&
(!path3_new_frame || new_frame != path3_new_frame) &&
(!path4_new_frame || new_frame != path4_new_frame) &&
(!path5_new_frame || new_frame != path5_new_frame))
dolby_vision_update_src_format(new_frame, 1);
else if (!new_frame &&
vd_layer[0].dispbuf &&
!is_local_vf(vd_layer[0].dispbuf))
dolby_vision_update_src_format(vd_layer[0].dispbuf, 0);
/* pause and video off->on case */
}
#endif
if (!new_frame && vd_layer[0].dispbuf &&
is_local_vf(vd_layer[0].dispbuf)) {
if (cur_blackout) {
vd_layer[0].property_changed = false;
} else if (!is_di_post_mode(vd_layer[0].dispbuf)) {
if (vd_layer[0].switch_vf && vd_layer[0].vf_ext)
vd_layer[0].vf_ext->canvas0Addr =
get_layer_display_canvas(0);
else
vd_layer[0].dispbuf->canvas0Addr =
get_layer_display_canvas(0);
}
}
if (vd_layer[0].dispbuf &&
(vd_layer[0].dispbuf->flag & (VFRAME_FLAG_VIDEO_COMPOSER |
VFRAME_FLAG_VIDEO_DRM)) &&
!(vd_layer[0].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME) &&
!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) {
int mirror = 0;
axis[0] = vd_layer[0].dispbuf->axis[0];
axis[1] = vd_layer[0].dispbuf->axis[1];
axis[2] = vd_layer[0].dispbuf->axis[2];
axis[3] = vd_layer[0].dispbuf->axis[3];
crop[0] = vd_layer[0].dispbuf->crop[0];
crop[1] = vd_layer[0].dispbuf->crop[1];
crop[2] = vd_layer[0].dispbuf->crop[2];
crop[3] = vd_layer[0].dispbuf->crop[3];
_set_video_window(&glayer_info[0], axis);
source_type = vd_layer[0].dispbuf->source_type;
if (source_type != VFRAME_SOURCE_TYPE_HDMI &&
source_type != VFRAME_SOURCE_TYPE_CVBS &&
source_type != VFRAME_SOURCE_TYPE_TUNER &&
source_type != VFRAME_SOURCE_TYPE_HWC)
_set_video_crop(&glayer_info[0], crop);
if (vd_layer[0].dispbuf->flag & VFRAME_FLAG_MIRROR_H)
mirror = H_MIRROR;
if (vd_layer[0].dispbuf->flag & VFRAME_FLAG_MIRROR_V)
mirror = V_MIRROR;
_set_video_mirror(&glayer_info[0], mirror);
set_alpha_scpxn(&vd_layer[0], vd_layer[0].dispbuf->componser_info);
glayer_info[0].zorder = vd_layer[0].dispbuf->zorder;
}
/* setting video display property in underflow mode */
if (!new_frame &&
vd_layer[0].dispbuf &&
(vd_layer[0].property_changed ||
is_picmode_changed(0, vd_layer[0].dispbuf))) {
primary_swap_frame(&vd_layer[0], vd_layer[0].dispbuf, __LINE__);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
dvel_swap_frame(cur_dispbuf2);
#endif
} else if (new_frame) {
vframe_walk_delay = (int)div_u64(((jiffies_64 -
new_frame->ready_jiffies64) * 1000), HZ);
vframe_walk_delay += 1000 *
vsync_pts_inc_scale / vsync_pts_inc_scale_base;
vframe_walk_delay -= new_frame->duration / 96;
#ifdef CONFIG_AMLOGIC_MEDIA_FRC
vframe_walk_delay += frc_get_video_latency();
#endif
primary_swap_frame(&vd_layer[0], new_frame, __LINE__);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
dvel_swap_frame(cur_dispbuf2);
#endif
}
/* TODO: need check more vd layer, now only vd1 */
if (vd_layer[0].dispbuf &&
(atomic_read(&vt_unreg_flag) ||
tvin_vf_is_keeped(vd_layer[0].dispbuf))) {
source_type = vd_layer[0].dispbuf->source_type;
/* TODO: change new flag to detect video tunnel path */
if (source_type == VFRAME_SOURCE_TYPE_HDMI ||
source_type == VFRAME_SOURCE_TYPE_CVBS ||
source_type == VFRAME_SOURCE_TYPE_TUNER) {
if (!vd_layer[0].force_disable) {
safe_switch_videolayer(0, false, true);
atomic_set(&vt_disable_video_done, 0);
}
vd_layer[0].force_disable = true;
} else {
vd_layer[0].force_disable = false;
}
} else {
vd_layer[0].force_disable = false;
}
if (cur_frame_par) {
if (cur_dev->aisr_enable &&
cur_dev->aisr_frame_parms.aisr_enable)
cur_frame_par->aisr_enable = 1;
else
cur_frame_par->aisr_enable = 0;
}
#if defined(CONFIG_AMLOGIC_MEDIA_FRC)
frc_input_handle(vd_layer[0].dispbuf, cur_frame_par);
#endif
if (atomic_read(&axis_changed)) {
video_prop_status |= VIDEO_PROP_CHANGE_AXIS;
atomic_set(&axis_changed, 0);
}
if (vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF)
vd_layer[0].keep_frame_id = 0;
else if (vd1_path_id == VFM_PATH_PIP)
vd_layer[0].keep_frame_id = 1;
else if (vd1_path_id == VFM_PATH_PIP2)
vd_layer[0].keep_frame_id = 2;
else
vd_layer[0].keep_frame_id = 0xff;
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
refresh_on_vs(new_frame, vd_layer[0].dispbuf);
amvecm_on_vs
(!is_local_vf(vd_layer[0].dispbuf)
? vd_layer[0].dispbuf : NULL,
new_frame,
new_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,
cur_frame_par ?
cur_frame_par->spsc1_w_in :
0,
cur_frame_par ?
cur_frame_par->spsc1_h_in :
0,
cur_frame_par ?
cur_frame_par->cm_input_w :
0,
cur_frame_par ?
cur_frame_par->cm_input_h :
0,
VD1_PATH,
VPP_TOP0);
#endif
/* work around which dec/vdin don't call update src_fmt function */
if (vd_layer[0].dispbuf && !is_local_vf(vd_layer[0].dispbuf)) {
int new_src_fmt = -1;
u32 src_map[] = {
VFRAME_SIGNAL_FMT_INVALID,
VFRAME_SIGNAL_FMT_HDR10,
VFRAME_SIGNAL_FMT_HDR10PLUS,
VFRAME_SIGNAL_FMT_DOVI,
VFRAME_SIGNAL_FMT_HDR10PRIME,
VFRAME_SIGNAL_FMT_HLG,
VFRAME_SIGNAL_FMT_SDR,
VFRAME_SIGNAL_FMT_MVC
};
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable())
new_src_fmt = get_dolby_vision_src_format();
else
#endif
new_src_fmt =
(int)get_cur_source_type(VD1_PATH, VPP_TOP0);
#endif
if (new_src_fmt > 0 && new_src_fmt < 8)
fmt = (enum vframe_signal_fmt_e)src_map[new_src_fmt];
else
fmt = VFRAME_SIGNAL_FMT_INVALID;
if (fmt != atomic_read(&cur_primary_src_fmt)) {
/* atomic_set(&primary_src_fmt, fmt); */
if (debug_flag & DEBUG_FLAG_TRACE_EVENT) {
char *old_str = NULL, *new_str = NULL;
enum vframe_signal_fmt_e old_fmt;
old_fmt = (enum vframe_signal_fmt_e)
atomic_read(&cur_primary_src_fmt);
if (old_fmt != VFRAME_SIGNAL_FMT_INVALID)
old_str = (char *)src_fmt_str[old_fmt];
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
new_str = (char *)src_fmt_str[fmt];
pr_info("VD1 src fmt changed: %s->%s. vf: %p, signal_type:0x%x\n",
old_str ? old_str : "invalid",
new_str ? new_str : "invalid",
vd_layer[0].dispbuf,
vd_layer[0].dispbuf->signal_type);
}
atomic_set(&cur_primary_src_fmt, fmt);
atomic_set(&primary_src_fmt, fmt);
video_prop_status |= VIDEO_PROP_CHANGE_FMT;
}
}
if (vd_layer[1].dispbuf_mapping == &cur_dispbuf &&
(cur_dispbuf == &vf_local ||
!cur_dispbuf) &&
vd_layer[1].dispbuf != cur_dispbuf)
vd_layer[1].dispbuf = cur_dispbuf;
if (vd_layer[1].dispbuf_mapping == &cur_pipbuf &&
(cur_pipbuf == &local_pip ||
!cur_pipbuf) &&
vd_layer[1].dispbuf != cur_pipbuf)
vd_layer[1].dispbuf = cur_pipbuf;
if (vd_layer[1].dispbuf_mapping == &cur_pipbuf2 &&
(cur_pipbuf2 == &local_pip2 ||
!cur_pipbuf2) &&
vd_layer[1].dispbuf != cur_pipbuf2)
vd_layer[1].dispbuf = cur_pipbuf2;
if (gvideo_recv[0] &&
vd_layer[1].dispbuf_mapping == &gvideo_recv[0]->cur_buf &&
(gvideo_recv[0]->cur_buf == &gvideo_recv[0]->local_buf ||
!gvideo_recv[0]->cur_buf) &&
vd_layer[1].dispbuf != gvideo_recv[0]->cur_buf)
vd_layer[1].dispbuf = gvideo_recv[0]->cur_buf;
if (gvideo_recv[1] &&
vd_layer[1].dispbuf_mapping == &gvideo_recv[1]->cur_buf &&
(gvideo_recv[1]->cur_buf == &gvideo_recv[1]->local_buf ||
!gvideo_recv[1]->cur_buf) &&
vd_layer[1].dispbuf != gvideo_recv[1]->cur_buf)
vd_layer[1].dispbuf = gvideo_recv[1]->cur_buf;
if (gvideo_recv[2] &&
vd_layer[1].dispbuf_mapping == &gvideo_recv[2]->cur_buf &&
(gvideo_recv[2]->cur_buf == &gvideo_recv[2]->local_buf ||
!gvideo_recv[2]->cur_buf) &&
vd_layer[1].dispbuf != gvideo_recv[2]->cur_buf)
vd_layer[1].dispbuf = gvideo_recv[2]->cur_buf;
if (vd_layer[1].switch_vf &&
vd_layer[1].dispbuf &&
vd_layer[1].dispbuf->vf_ext)
vd_layer[1].vf_ext =
(struct vframe_s *)vd_layer[1].dispbuf->vf_ext;
else
vd_layer[1].vf_ext = NULL;
/* vd2 config */
if (gvideo_recv[0] &&
gvideo_recv[0]->path_id == vd2_path_id) {
/* video_render.0 display on VD2 */
new_frame2 = path3_new_frame;
if (!new_frame2) {
if (!gvideo_recv[0]->cur_buf) {
/* video_render.0 no frame in display */
if (cur_vd2_path_id != vd2_path_id)
safe_switch_videolayer(1, false, true);
vd_layer[1].dispbuf = NULL;
} else if (gvideo_recv[0]->cur_buf ==
&gvideo_recv[0]->local_buf) {
/* video_render.0 keep frame */
vd_layer[1].dispbuf = gvideo_recv[0]->cur_buf;
} else if (vd_layer[1].dispbuf
!= gvideo_recv[0]->cur_buf) {
/* video_render.0 has frame in display */
new_frame2 = gvideo_recv[0]->cur_buf;
}
}
if (new_frame2 || gvideo_recv[0]->cur_buf)
vd_layer[1].dispbuf_mapping = &gvideo_recv[0]->cur_buf;
cur_blackout = 1;
} else if (gvideo_recv[1] &&
(gvideo_recv[1]->path_id == vd2_path_id)) {
/* video_render.1 display on VD2 */
new_frame2 = path4_new_frame;
if (!new_frame2) {
if (!gvideo_recv[1]->cur_buf) {
/* video_render.1 no frame in display */
if (cur_vd2_path_id != vd2_path_id)
safe_switch_videolayer(1, false, true);
vd_layer[1].dispbuf = NULL;
} else if (gvideo_recv[1]->cur_buf ==
&gvideo_recv[1]->local_buf) {
/* video_render.1 keep frame */
vd_layer[1].dispbuf = gvideo_recv[1]->cur_buf;
} else if (vd_layer[1].dispbuf
!= gvideo_recv[1]->cur_buf) {
/* video_render.1 has frame in display */
new_frame2 = gvideo_recv[1]->cur_buf;
}
}
if (new_frame2 || gvideo_recv[1]->cur_buf)
vd_layer[1].dispbuf_mapping = &gvideo_recv[1]->cur_buf;
cur_blackout = 1;
} else if (gvideo_recv[2] &&
(gvideo_recv[2]->path_id == vd2_path_id)) {
/* video_render.2 display on VD2 */
new_frame2 = path5_new_frame;
if (!new_frame2) {
if (!gvideo_recv[2]->cur_buf) {
/* video_render.2 no frame in display */
if (cur_vd2_path_id != vd2_path_id)
safe_switch_videolayer(1, false, true);
vd_layer[1].dispbuf = NULL;
} else if (gvideo_recv[2]->cur_buf ==
&gvideo_recv[2]->local_buf) {
/* video_render.2 keep frame */
vd_layer[1].dispbuf = gvideo_recv[2]->cur_buf;
} else if (vd_layer[1].dispbuf
!= gvideo_recv[2]->cur_buf) {
/* video_render.2 has frame in display */
new_frame2 = gvideo_recv[2]->cur_buf;
}
}
if (new_frame2 || gvideo_recv[2]->cur_buf)
vd_layer[1].dispbuf_mapping = &gvideo_recv[2]->cur_buf;
pr_info("new_frame2=%p\n", new_frame2);
cur_blackout = 1;
} else if (vd2_path_id == VFM_PATH_AMVIDEO) {
/* priamry display in VD2 */
new_frame2 = path0_new_frame;
if (!new_frame2) {
if (!cur_dispbuf) {
/* primary no frame in display */
if (cur_vd2_path_id != vd2_path_id)
safe_switch_videolayer(1, false, true);
vd_layer[1].dispbuf = NULL;
} else if (cur_dispbuf == &vf_local) {
/* priamry keep frame */
vd_layer[1].dispbuf = cur_dispbuf;
} else if (vd_layer[1].dispbuf
!= cur_dispbuf) {
new_frame2 = cur_dispbuf;
}
}
if (new_frame2 || cur_dispbuf)
vd_layer[1].dispbuf_mapping = &cur_dispbuf;
cur_blackout = blackout | force_blackout;
} else if (vd2_path_id == VFM_PATH_PIP2) {
/* pip display in VD3 */
new_frame2 = path2_new_frame;
if (!new_frame2) {
if (!cur_pipbuf2) {
/* pip no display frame */
if (cur_vd2_path_id != vd2_path_id)
safe_switch_videolayer(1, false, true);
vd_layer[1].dispbuf = NULL;
} else if (cur_pipbuf2 == &local_pip2) {
/* pip keep frame */
vd_layer[1].dispbuf = cur_pipbuf2;
} else if (vd_layer[1].dispbuf
!= cur_pipbuf2) {
new_frame2 = cur_pipbuf2;
}
}
if (new_frame2 || cur_pipbuf2)
vd_layer[1].dispbuf_mapping = &cur_pipbuf2;
cur_blackout = blackout_pip2 | force_blackout;
} else if (vd2_path_id != VFM_PATH_INVALID) {
/* pip display in VD2 */
new_frame2 = path1_new_frame;
if (!new_frame2) {
if (!cur_pipbuf) {
/* pip no display frame */
if (cur_vd2_path_id != vd2_path_id)
safe_switch_videolayer(1, false, true);
vd_layer[1].dispbuf = NULL;
} else if (cur_pipbuf == &local_pip) {
/* pip keep frame */
vd_layer[1].dispbuf = cur_pipbuf;
} else if (vd_layer[1].dispbuf
!= cur_pipbuf) {
new_frame2 = cur_pipbuf;
}
}
if (new_frame2 || cur_pipbuf)
vd_layer[1].dispbuf_mapping = &cur_pipbuf;
cur_blackout = blackout_pip | force_blackout;
} else {
cur_blackout = 1;
}
if (!new_frame2 && vd_layer[1].dispbuf &&
is_local_vf(vd_layer[1].dispbuf)) {
if (cur_blackout) {
vd_layer[1].property_changed = false;
} else if (vd_layer[1].dispbuf) {
if (vd_layer[1].switch_vf && vd_layer[1].vf_ext)
vd_layer[1].vf_ext->canvas0Addr =
get_layer_display_canvas(1);
else
vd_layer[1].dispbuf->canvas0Addr =
get_layer_display_canvas(1);
}
}
if (vd_layer[1].dispbuf &&
(vd_layer[1].dispbuf->flag & (VFRAME_FLAG_VIDEO_COMPOSER |
VFRAME_FLAG_VIDEO_DRM)) &&
!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) {
int mirror = 0;
axis[0] = vd_layer[1].dispbuf->axis[0];
axis[1] = vd_layer[1].dispbuf->axis[1];
axis[2] = vd_layer[1].dispbuf->axis[2];
axis[3] = vd_layer[1].dispbuf->axis[3];
crop[0] = vd_layer[1].dispbuf->crop[0];
crop[1] = vd_layer[1].dispbuf->crop[1];
crop[2] = vd_layer[1].dispbuf->crop[2];
crop[3] = vd_layer[1].dispbuf->crop[3];
_set_video_window(&glayer_info[1], axis);
source_type = vd_layer[1].dispbuf->source_type;
if (source_type != VFRAME_SOURCE_TYPE_HDMI &&
source_type != VFRAME_SOURCE_TYPE_CVBS &&
source_type != VFRAME_SOURCE_TYPE_TUNER &&
source_type != VFRAME_SOURCE_TYPE_HWC)
_set_video_crop(&glayer_info[1], crop);
if (vd_layer[1].dispbuf->flag & VFRAME_FLAG_MIRROR_H)
mirror = H_MIRROR;
if (vd_layer[1].dispbuf->flag & VFRAME_FLAG_MIRROR_V)
mirror = V_MIRROR;
_set_video_mirror(&glayer_info[1], mirror);
set_alpha_scpxn(&vd_layer[1], vd_layer[1].dispbuf->componser_info);
glayer_info[1].zorder = vd_layer[1].dispbuf->zorder;
}
/* setting video display property in underflow mode */
if (!new_frame2 &&
vd_layer[1].dispbuf &&
(vd_layer[1].property_changed ||
is_picmode_changed(1, vd_layer[1].dispbuf))) {
pip_swap_frame(&vd_layer[1], vd_layer[1].dispbuf, vinfo);
need_disable_vd2 = false;
} else if (new_frame2) {
pip_swap_frame(&vd_layer[1], new_frame2, vinfo);
need_disable_vd2 = false;
}
if (vd2_path_id == VFM_PATH_PIP ||
vd2_path_id == VFM_PATH_DEF)
vd_layer[1].keep_frame_id = 1;
else if (vd2_path_id == VFM_PATH_PIP2)
vd_layer[1].keep_frame_id = 2;
else if (vd2_path_id == VFM_PATH_AMVIDEO)
vd_layer[1].keep_frame_id = 0;
else
vd_layer[1].keep_frame_id = 0xff;
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
amvecm_on_vs
(!is_local_vf(vd_layer[1].dispbuf)
? vd_layer[1].dispbuf : NULL,
new_frame2,
new_frame2 ? CSC_FLAG_TOGGLE_FRAME : 0,
curpip_frame_par ?
curpip_frame_par->supsc1_hori_ratio :
0,
curpip_frame_par ?
curpip_frame_par->supsc1_vert_ratio :
0,
curpip_frame_par ?
curpip_frame_par->spsc1_w_in :
0,
curpip_frame_par ?
curpip_frame_par->spsc1_h_in :
0,
curpip_frame_par ?
curpip_frame_par->cm_input_w :
0,
curpip_frame_par ?
curpip_frame_par->cm_input_h :
0,
VD2_PATH,
VPP_TOP0);
#endif
if (need_disable_vd2) {
safe_switch_videolayer(1, false, true);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
/* reset dvel statue when disable vd2 */
dvel_status = false;
#endif
}
/* karry ? */
if (cur_dev->max_vd_layers == 3) {
if (vd_layer[2].dispbuf_mapping == &cur_dispbuf &&
(cur_dispbuf == &vf_local ||
!cur_dispbuf) &&
vd_layer[2].dispbuf != cur_dispbuf)
vd_layer[2].dispbuf = cur_dispbuf;
if (vd_layer[2].dispbuf_mapping == &cur_pipbuf &&
(cur_pipbuf == &local_pip ||
!cur_pipbuf) &&
vd_layer[2].dispbuf != cur_pipbuf)
vd_layer[2].dispbuf = cur_pipbuf;
if (vd_layer[2].dispbuf_mapping == &cur_pipbuf2 &&
(cur_pipbuf2 == &local_pip2 ||
!cur_pipbuf2) &&
vd_layer[2].dispbuf != cur_pipbuf2)
vd_layer[2].dispbuf = cur_pipbuf2;
if (gvideo_recv[0] &&
vd_layer[2].dispbuf_mapping == &gvideo_recv[0]->cur_buf &&
(gvideo_recv[0]->cur_buf == &gvideo_recv[0]->local_buf ||
!gvideo_recv[0]->cur_buf) &&
vd_layer[2].dispbuf != gvideo_recv[0]->cur_buf)
vd_layer[2].dispbuf = gvideo_recv[0]->cur_buf;
if (gvideo_recv[1] &&
vd_layer[2].dispbuf_mapping == &gvideo_recv[1]->cur_buf &&
(gvideo_recv[1]->cur_buf == &gvideo_recv[1]->local_buf ||
!gvideo_recv[1]->cur_buf) &&
vd_layer[2].dispbuf != gvideo_recv[1]->cur_buf)
vd_layer[2].dispbuf = gvideo_recv[1]->cur_buf;
if (gvideo_recv[2] &&
vd_layer[2].dispbuf_mapping == &gvideo_recv[2]->cur_buf &&
(gvideo_recv[2]->cur_buf == &gvideo_recv[2]->local_buf ||
!gvideo_recv[2]->cur_buf) &&
vd_layer[2].dispbuf != gvideo_recv[2]->cur_buf)
vd_layer[2].dispbuf = gvideo_recv[2]->cur_buf;
if (vd_layer[2].switch_vf &&
vd_layer[2].dispbuf &&
vd_layer[2].dispbuf->vf_ext)
vd_layer[2].vf_ext =
(struct vframe_s *)vd_layer[2].dispbuf->vf_ext;
else
vd_layer[2].vf_ext = NULL;
/* vd3 config */
if (gvideo_recv[0] &&
gvideo_recv[0]->path_id == vd3_path_id) {
/* video_render.0 display on VD3 */
new_frame3 = path3_new_frame;
if (!new_frame3) {
if (!gvideo_recv[0]->cur_buf) {
/* video_render.0 no frame in display */
if (cur_vd3_path_id != vd3_path_id)
safe_switch_videolayer(2, false, true);
vd_layer[2].dispbuf = NULL;
} else if (gvideo_recv[0]->cur_buf ==
&gvideo_recv[0]->local_buf) {
/* video_render.0 keep frame */
vd_layer[2].dispbuf = gvideo_recv[0]->cur_buf;
} else if (vd_layer[2].dispbuf
!= gvideo_recv[0]->cur_buf) {
/* video_render.0 has frame in display */
new_frame3 = gvideo_recv[0]->cur_buf;
}
}
if (new_frame3 || gvideo_recv[0]->cur_buf)
vd_layer[2].dispbuf_mapping = &gvideo_recv[0]->cur_buf;
cur_blackout = 1;
} else if (gvideo_recv[1] &&
(gvideo_recv[1]->path_id == vd3_path_id)) {
/* video_render.1 display on VD3 */
new_frame3 = path4_new_frame;
if (!new_frame3) {
if (!gvideo_recv[1]->cur_buf) {
/* video_render.1 no frame in display */
if (cur_vd3_path_id != vd3_path_id)
safe_switch_videolayer(2, false, true);
vd_layer[2].dispbuf = NULL;
} else if (gvideo_recv[1]->cur_buf ==
&gvideo_recv[1]->local_buf) {
/* video_render.1 keep frame */
vd_layer[2].dispbuf = gvideo_recv[1]->cur_buf;
} else if (vd_layer[2].dispbuf
!= gvideo_recv[1]->cur_buf) {
/* video_render.1 has frame in display */
new_frame3 = gvideo_recv[1]->cur_buf;
}
}
if (new_frame3 || gvideo_recv[1]->cur_buf)
vd_layer[2].dispbuf_mapping = &gvideo_recv[1]->cur_buf;
cur_blackout = 1;
} else if (gvideo_recv[2] &&
(gvideo_recv[2]->path_id == vd3_path_id)) {
/* video_render.2 display on VD3 */
new_frame3 = path5_new_frame;
if (!new_frame3) {
if (!gvideo_recv[2]->cur_buf) {
/* video_render.2 no frame in display */
if (cur_vd3_path_id != vd3_path_id)
safe_switch_videolayer(2, false, true);
vd_layer[2].dispbuf = NULL;
} else if (gvideo_recv[2]->cur_buf ==
&gvideo_recv[2]->local_buf) {
/* video_render.2 keep frame */
vd_layer[2].dispbuf = gvideo_recv[2]->cur_buf;
} else if (vd_layer[2].dispbuf
!= gvideo_recv[2]->cur_buf) {
/* video_render.2 has frame in display */
new_frame3 = gvideo_recv[2]->cur_buf;
}
}
if (new_frame3 || gvideo_recv[2]->cur_buf)
vd_layer[2].dispbuf_mapping = &gvideo_recv[2]->cur_buf;
cur_blackout = 1;
} else if (vd3_path_id == VFM_PATH_AMVIDEO) {
/* priamry display in VD3 */
new_frame3 = path0_new_frame;
if (!new_frame3) {
if (!cur_dispbuf) {
/* primary no frame in display */
if (cur_vd3_path_id != vd3_path_id)
safe_switch_videolayer(2, false, true);
vd_layer[2].dispbuf = NULL;
} else if (cur_dispbuf == &vf_local) {
/* priamry keep frame */
vd_layer[2].dispbuf = cur_dispbuf;
} else if (vd_layer[2].dispbuf
!= cur_dispbuf) {
new_frame3 = cur_dispbuf;
}
}
if (new_frame3 || cur_dispbuf)
vd_layer[2].dispbuf_mapping = &cur_dispbuf;
cur_blackout = blackout | force_blackout;
} else if (vd3_path_id == VFM_PATH_PIP) {
/* pip2 display in VD3 */
new_frame3 = path1_new_frame;
if (!new_frame3) {
if (!cur_pipbuf) {
/* pip no display frame */
if (cur_vd3_path_id != vd3_path_id)
safe_switch_videolayer(2, false, true);
vd_layer[2].dispbuf = NULL;
} else if (cur_pipbuf == &local_pip) {
/* pip keep frame */
vd_layer[2].dispbuf = cur_pipbuf;
} else if (vd_layer[2].dispbuf
!= cur_pipbuf) {
new_frame3 = cur_pipbuf;
}
}
if (new_frame3 || cur_pipbuf)
vd_layer[2].dispbuf_mapping = &cur_pipbuf;
cur_blackout = blackout_pip | force_blackout;
} else if (vd3_path_id != VFM_PATH_INVALID) {
/* pip2 display in VD3 */
new_frame3 = path2_new_frame;
if (!new_frame3) {
if (!cur_pipbuf2) {
/* pip no display frame */
if (cur_vd3_path_id != vd3_path_id)
safe_switch_videolayer(2, false, true);
vd_layer[2].dispbuf = NULL;
} else if (cur_pipbuf2 == &local_pip2) {
/* pip keep frame */
vd_layer[2].dispbuf = cur_pipbuf2;
} else if (vd_layer[2].dispbuf
!= cur_pipbuf2) {
new_frame3 = cur_pipbuf2;
}
}
if (new_frame3 || cur_pipbuf2)
vd_layer[2].dispbuf_mapping = &cur_pipbuf2;
cur_blackout = blackout_pip2 | force_blackout;
} else {
cur_blackout = 1;
}
if (!new_frame3 && vd_layer[2].dispbuf &&
is_local_vf(vd_layer[2].dispbuf)) {
if (cur_blackout) {
vd_layer[2].property_changed = false;
} else if (vd_layer[2].dispbuf) {
if (vd_layer[2].switch_vf && vd_layer[1].vf_ext)
vd_layer[2].vf_ext->canvas0Addr =
get_layer_display_canvas(2);
else
vd_layer[2].dispbuf->canvas0Addr =
get_layer_display_canvas(2);
}
}
if (vd_layer[2].dispbuf &&
(vd_layer[2].dispbuf->flag & (VFRAME_FLAG_VIDEO_COMPOSER |
VFRAME_FLAG_VIDEO_DRM)) &&
!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) {
axis[0] = vd_layer[2].dispbuf->axis[0];
axis[1] = vd_layer[2].dispbuf->axis[1];
axis[2] = vd_layer[2].dispbuf->axis[2];
axis[3] = vd_layer[2].dispbuf->axis[3];
crop[0] = vd_layer[2].dispbuf->crop[0];
crop[1] = vd_layer[2].dispbuf->crop[1];
crop[2] = vd_layer[2].dispbuf->crop[2];
crop[3] = vd_layer[2].dispbuf->crop[3];
_set_video_window(&glayer_info[2], axis);
source_type = vd_layer[2].dispbuf->source_type;
if (source_type != VFRAME_SOURCE_TYPE_HDMI &&
source_type != VFRAME_SOURCE_TYPE_CVBS &&
source_type != VFRAME_SOURCE_TYPE_TUNER &&
source_type != VFRAME_SOURCE_TYPE_HWC)
_set_video_crop(&glayer_info[2], crop);
set_alpha_scpxn(&vd_layer[2], vd_layer[2].dispbuf->componser_info);
glayer_info[2].zorder = vd_layer[2].dispbuf->zorder;
}
/* setting video display property in underflow mode */
if (!new_frame3 &&
vd_layer[2].dispbuf &&
(vd_layer[2].property_changed ||
is_picmode_changed(2, vd_layer[2].dispbuf))) {
pip2_swap_frame(&vd_layer[2], vd_layer[2].dispbuf, vinfo);
need_disable_vd3 = false;
} else if (new_frame3) {
pip2_swap_frame(&vd_layer[2], new_frame3, vinfo);
need_disable_vd3 = false;
}
if (vd3_path_id == VFM_PATH_PIP2 ||
vd3_path_id == VFM_PATH_DEF)
vd_layer[2].keep_frame_id = 2;
else if (vd3_path_id == VFM_PATH_PIP)
vd_layer[2].keep_frame_id = 1;
else if (vd3_path_id == VFM_PATH_AMVIDEO)
vd_layer[2].keep_frame_id = 0;
else
vd_layer[2].keep_frame_id = 0xff;
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
amvecm_on_vs
(!is_local_vf(vd_layer[2].dispbuf)
? vd_layer[2].dispbuf : NULL,
new_frame3,
new_frame3 ? CSC_FLAG_TOGGLE_FRAME : 0,
curpip2_frame_par ?
curpip2_frame_par->supsc1_hori_ratio :
0,
curpip2_frame_par ?
curpip2_frame_par->supsc1_vert_ratio :
0,
curpip2_frame_par ?
curpip2_frame_par->spsc1_w_in :
0,
curpip2_frame_par ?
curpip2_frame_par->spsc1_h_in :
0,
curpip2_frame_par ?
curpip2_frame_par->cm_input_w :
0,
curpip2_frame_par ?
curpip2_frame_par->cm_input_h :
0,
VD3_PATH,
VPP_TOP0);
#endif
if (need_disable_vd3)
safe_switch_videolayer(2, false, true);
}
/* filter setting management */
frame_par_di_set = primary_render_frame(&vd_layer[0]);
pip_render_frame(&vd_layer[1], vinfo);
pip2_render_frame(&vd_layer[2], vinfo);
video_secure_set();
if (vd_layer[0].dispbuf &&
(vd_layer[0].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME)) {
if ((vd_layer[0].force_black &&
!(debug_flag & DEBUG_FLAG_NO_CLIP_SETTING)) ||
!vd_layer[0].force_black) {
if (vd_layer[0].dispbuf->type & VIDTYPE_RGB_444) {
/* RGB */
vd_layer[0].clip_setting.clip_max =
(0x0 << 20) | (0x0 << 10) | 0;
vd_layer[0].clip_setting.clip_min =
vd_layer[0].clip_setting.clip_max;
} else {
/* YUV */
vd_layer[0].clip_setting.clip_max =
(0x0 << 20) | (0x200 << 10) | 0x200;
vd_layer[0].clip_setting.clip_min =
vd_layer[0].clip_setting.clip_max;
}
vd_layer[0].clip_setting.clip_done = false;
}
if (!vd_layer[0].force_black) {
pr_debug("vsync: vd1 force black\n");
vd_layer[0].force_black = true;
}
} else if (vd_layer[0].force_black) {
pr_debug("vsync: vd1 black to normal\n");
vd_layer[0].clip_setting.clip_max =
(0x3ff << 20) | (0x3ff << 10) | 0x3ff;
vd_layer[0].clip_setting.clip_min = 0;
vd_layer[0].clip_setting.clip_done = false;
vd_layer[0].force_black = false;
}
if (vd_layer[1].dispbuf &&
(vd_layer[1].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME))
safe_switch_videolayer(1, false, true);
if (vd_layer[2].dispbuf &&
(vd_layer[2].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME))
safe_switch_videolayer(2, false, true);
if ((cur_vd1_path_id != vd1_path_id ||
cur_vd2_path_id != vd2_path_id ||
cur_vd3_path_id != vd3_path_id) &&
(debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) {
pr_info("VID: === After path switch ===\n");
pr_info("VID: \tpath_id: %d, %d, %d;\nVID: \ttoggle:%p, %p, %p %p, %p, %p\nVID: \tcur:%p, %p, %p, %p, %p, %p;\n",
vd1_path_id, vd2_path_id, vd3_path_id,
path0_new_frame, path1_new_frame,
path2_new_frame, path3_new_frame,
path4_new_frame, path5_new_frame,
cur_dispbuf, cur_pipbuf, cur_pipbuf2,
gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL,
gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL,
gvideo_recv[2] ? gvideo_recv[2]->cur_buf : NULL);
pr_info("VID: \tdispbuf:%p, %p, %p; \tvf_ext:%p, %p, %p;\nVID: \tlocal:%p, %p, %p, %p, %p, %p\n",
vd_layer[0].dispbuf, vd_layer[1].dispbuf, vd_layer[2].dispbuf,
vd_layer[0].vf_ext, vd_layer[1].vf_ext, vd_layer[2].vf_ext,
&vf_local, &local_pip, &local_pip2,
gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL,
gvideo_recv[2] ? &gvideo_recv[2]->local_buf : NULL);
pr_info("VID: \tblackout:%d %d, %d force:%d;\n",
blackout, blackout_pip, blackout_pip2, force_blackout);
}
if (vd_layer[0].dispbuf &&
(vd_layer[0].dispbuf->type & VIDTYPE_MVC))
vd_layer[0].enable_3d_mode = mode_3d_mvc_enable;
else if (process_3d_type)
vd_layer[0].enable_3d_mode = mode_3d_enable;
else
vd_layer[0].enable_3d_mode = mode_3d_disable;
/* all frames has been renderred, so reset new frame flag */
vd_layer[0].new_frame = false;
vd_layer[1].new_frame = false;
vd_layer[2].new_frame = false;
if (cur_dispbuf && cur_dispbuf->process_fun &&
(vd1_path_id == VFM_PATH_AMVIDEO ||
vd1_path_id == VFM_PATH_DEF))
di_post_vf = cur_dispbuf;
else if (vd_layer[0].dispbuf &&
vd_layer[0].dispbuf->process_fun &&
is_di_post_mode(vd_layer[0].dispbuf))
di_post_vf = vd_layer[0].dispbuf;
if (vd_layer[0].do_switch)
di_post_vf = NULL;
if (di_post_vf) {
/* 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
if (cur_frame_par)
di_post_vf->process_fun
(di_post_vf->private_data,
vd_layer[0].start_x_lines |
(cur_frame_par->vscale_skip_count <<
24) | (frame_par_di_set << 16),
vd_layer[0].end_x_lines,
vd_layer[0].start_y_lines,
vd_layer[0].end_y_lines,
di_post_vf);
di_post_process_done = true;
}
if (vd_layer[0].dispbuf) {
pq_process_debug[0] = ai_pq_value;
pq_process_debug[1] = ai_pq_disable;
pq_process_debug[2] = ai_pq_debug;
pq_process_debug[3] = ai_pq_policy;
#ifdef CONFIG_AMLOGIC_VDETECT
vdetect_get_frame_nn_info(vd_layer[0].dispbuf);
#endif
vf_pq_process(vd_layer[0].dispbuf, vpp_scenes, pq_process_debug);
if (ai_pq_debug > 0x10) {
ai_pq_debug--;
if (ai_pq_debug == 0x10)
ai_pq_debug = 0;
}
memcpy(nn_scenes_value, vd_layer[0].dispbuf->nn_value,
sizeof(nn_scenes_value));
}
exit:
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
if (legacy_vpp &&
!di_post_process_done &&
is_di_post_on())
DI_POST_UPDATE_MC();
#endif
#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG)
pts_trace++;
#endif
vd_clip_setting(0, &vd_layer[0].clip_setting);
vd_clip_setting(1, &vd_layer[1].clip_setting);
if (cur_dev->max_vd_layers == 3)
vd_clip_setting(2, &vd_layer[2].clip_setting);
vpp_blend_update(vinfo);
if (gvideo_recv[0])
gvideo_recv[0]->func->late_proc(gvideo_recv[0]);
if (gvideo_recv[1])
gvideo_recv[1]->func->late_proc(gvideo_recv[1]);
if (gvideo_recv[2])
gvideo_recv[2]->func->late_proc(gvideo_recv[2]);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
cur_rdma_buf = cur_dispbuf;
pip_rdma_buf = cur_pipbuf;
pip2_rdma_buf = cur_pipbuf2;
RUN_FIRST_RDMA:
/* 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;
}
enc_line = get_cur_enc_line();
if (enc_line > vsync_exit_line_max)
vsync_exit_line_max = enc_line;
if (video_suspend)
video_suspend_cycle++;
#ifdef FIQ_VSYNC
if (video_notify_flag)
fiq_bridge_pulse_trigger(&vsync_fiq_bridge);
#else
if (video_notify_flag)
vsync_notify();
/* if prop_change not zero, event will be delayed to next vsync */
if (video_prop_status &&
!atomic_read(&video_prop_change)) {
if (debug_flag & DEBUG_FLAG_TRACE_EVENT)
pr_info("VD1 send event, changed status: 0x%x\n",
video_prop_status);
atomic_set(&video_prop_change, video_prop_status);
video_prop_status = VIDEO_PROP_CHANGE_NONE;
wake_up_interruptible(&amvideo_prop_change_wait);
}
if (video_info_change_status) {
struct vd_info_s vd_info;
if (debug_flag & DEBUG_FLAG_TRACE_EVENT)
pr_info("VD1 send event to frc, changed status: 0x%x\n",
video_info_change_status);
vd_info.flags = video_info_change_status;
vd_signal_notifier_call_chain(VIDEO_INFO_CHANGED,
&vd_info);
video_info_change_status = VIDEO_INFO_CHANGE_NONE;
}
vpu_work_process();
vpp_crc_result = vpp_crc_check(vpp_crc_en, VPP0);
cur_vd1_path_id = vd1_path_id;
cur_vd2_path_id = vd2_path_id;
cur_vd3_path_id = vd3_path_id;
if (debug_flag & DEBUG_FLAG_GET_COUNT)
pr_info("count=%d pip=%d, pip2=%d\n",
get_count, get_count_pip, get_count_pip2);
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
static irqreturn_t vsync_pre_vsync_isr(int irq, void *dev_id)
{
return IRQ_HANDLED;
}
/*********************************************************
* FIQ Routines
*********************************************************/
static void vsync_fiq_up(void)
{
#ifdef FIQ_VSYNC
request_fiq(INT_VIU_VSYNC, &vsync_fisr);
#else
int r;
r = request_irq(video_vsync, &vsync_isr,
IRQF_SHARED, "vsync", (void *)video_dev_id);
if (amvideo_meson_dev.cpu_type == MESON_CPU_MAJOR_ID_SC2_ ||
amvideo_meson_dev.has_vpp1)
r = request_irq(video_vsync_viu2, &vsync_isr_viu2,
IRQF_SHARED, "vsync_viu2",
(void *)video_dev_id);
if (amvideo_meson_dev.has_vpp2)
r = request_irq(video_vsync_viu3, &vsync_isr_viu3,
IRQF_SHARED, "vsync_viu3",
(void *)video_dev_id);
if (amvideo_meson_dev.dev_property.frc_support)
r = request_irq(video_pre_vsync, &vsync_pre_vsync_isr,
IRQF_SHARED, "pre_vsync",
(void *)video_dev_id);
if (r < 0)
pr_info("request irq fail, %d\n", r);
#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
free_irq(video_vsync, (void *)video_dev_id);
if (amvideo_meson_dev.cpu_type == MESON_CPU_MAJOR_ID_SC2_ ||
amvideo_meson_dev.has_vpp1)
free_irq(video_vsync_viu2, (void *)video_dev_id);
if (amvideo_meson_dev.has_vpp2)
free_irq(video_vsync_viu3, (void *)video_dev_id);
if (amvideo_meson_dev.dev_property.frc_support)
free_irq(video_pre_vsync, (void *)video_dev_id);
#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() &&
for_dolby_vision_certification()),
OP_FORCE_NOT_SWITCH_VF);
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)
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 release_di_buffer(int inst)
{
int i;
for (i = 0; i < recycle_cnt[inst]; i++) {
if (recycle_buf[inst][i] &&
IS_DI_POSTWRTIE(recycle_buf[inst][i]->type) &&
(recycle_buf[inst][i]->flag & VFRAME_FLAG_DI_PW_VFM)) {
di_release_count++;
dim_post_keep_cmd_release2(recycle_buf[inst][i]);
}
recycle_buf[inst][i] = NULL;
}
recycle_cnt[inst] = 0;
}
static void video_vf_unreg_provider(void)
{
ulong flags;
bool layer1_used = false;
bool layer2_used = false;
bool layer3_used = false;
struct vframe_s *el_vf = NULL;
int keeped = 0, ret = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
new_frame_count = 0;
first_frame_toggled = 0;
videopeek = 0;
nopostvideostart = false;
hold_property_changed = 0;
atomic_inc(&video_unreg_flag);
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);
ret = update_amvideo_recycle_buffer();
if (ret == -EAGAIN) {
/* The currently displayed vf is not added to the queue
* that needs to be released. You need to release the vf
* data in the release queue before adding the currently
* displayed vf to the release queue.
*/
release_di_buffer(0);
update_amvideo_recycle_buffer();
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
dispbuf_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
dispbuf_to_put[i] = NULL;
cur_rdma_buf = NULL;
#endif
if (cur_dispbuf) {
if (cur_dispbuf->vf_ext &&
IS_DI_POSTWRTIE(cur_dispbuf->type)) {
struct vframe_s *tmp =
(struct vframe_s *)cur_dispbuf->vf_ext;
memcpy(&tmp->pic_mode, &cur_dispbuf->pic_mode,
sizeof(struct vframe_pic_mode_s));
vf_local_ext = *tmp;
vf_local = *cur_dispbuf;
vf_local.vf_ext = (void *)&vf_local_ext;
} else {
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) {
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;
if (pip_loop) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
pipbuf_to_put[i] = 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;
}
if (pip2_loop) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
pipbuf2_to_put[i] = NULL;
pip2_rdma_buf = NULL;
#endif
if (cur_pipbuf2) {
local_pip2 = *cur_pipbuf2;
cur_pipbuf2 = &local_pip2;
cur_pipbuf2->video_angle = 0;
}
pip2_frame_count = 0;
}
spin_unlock_irqrestore(&lock, flags);
if (vd_layer[0].dispbuf_mapping
== &cur_dispbuf)
layer1_used = true;
if (vd_layer[1].dispbuf_mapping
== &cur_dispbuf)
layer2_used = true;
if (vd_layer[2].dispbuf_mapping
== &cur_dispbuf)
layer3_used = true;
if (layer1_used || !vd_layer[0].dispbuf_mapping)
atomic_set(&primary_src_fmt, VFRAME_SIGNAL_FMT_INVALID);
if (pip_loop) {
vd_layer[1].disable_video =
VIDEO_DISABLE_FORNEXT;
safe_switch_videolayer(1, false, false);
}
if (pip2_loop) {
vd_layer[2].disable_video =
VIDEO_DISABLE_FORNEXT;
safe_switch_videolayer(2, false, false);
}
if (!layer1_used && !layer2_used && !layer3_used)
cur_dispbuf = NULL;
if (blackout | force_blackout) {
if (layer1_used)
safe_switch_videolayer
(0, false, false);
if (layer2_used)
safe_switch_videolayer
(1, false, false);
if (layer3_used)
safe_switch_videolayer
(2, false, false);
try_free_keep_video(1);
}
if (cur_dispbuf)
keeped = vf_keep_current
(cur_dispbuf, el_vf);
pr_info("%s: vd1 used: %s, vd2 used: %s, vd3 used: %s, keep_ret:%d, black_out:%d, cur_dispbuf:%p\n",
__func__,
layer1_used ? "true" : "false",
layer2_used ? "true" : "false",
layer3_used ? "true" : "false",
keeped, blackout | force_blackout,
cur_dispbuf);
if (hdmi_in_onvideo == 0 && (video_start_post)) {
tsync_avevent(VIDEO_STOP, 0);
video_start_post = false;
}
if (keeped <= 0) {/*keep failed.*/
if (keeped < 0)
pr_info("keep frame failed, disable video now.\n");
else
pr_info("keep frame skip, disable video again.\n");
if (layer1_used)
safe_switch_videolayer
(0, false, false);
if (layer2_used)
safe_switch_videolayer
(1, false, false);
if (layer3_used)
safe_switch_videolayer
(2, false, false);
try_free_keep_video(1);
}
atomic_dec(&video_unreg_flag);
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 = 0;
time_setomxpts_last = 0;
vdin_err_crc_cnt = 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;
int ret = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
atomic_inc(&video_unreg_flag);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
ret = update_amvideo_recycle_buffer();
if (ret == -EAGAIN) {
/* The currently displayed vf is not added to the queue
* that needs to be released. You need to release the vf
* data in the release queue before adding the currently
* displayed vf to the release queue.
*/
release_di_buffer(0);
update_amvideo_recycle_buffer();
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
dispbuf_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
dispbuf_to_put[i] = NULL;
cur_rdma_buf = NULL;
#endif
if (cur_dispbuf) {
if (cur_dispbuf->vf_ext &&
IS_DI_POSTWRTIE(cur_dispbuf->type)) {
struct vframe_s *tmp =
(struct vframe_s *)cur_dispbuf->vf_ext;
memcpy(&tmp->pic_mode, &cur_dispbuf->pic_mode,
sizeof(struct vframe_pic_mode_s));
vf_local_ext = *tmp;
vf_local = *cur_dispbuf;
vf_local.vf_ext = (void *)&vf_local_ext;
} else {
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_dec(&video_unreg_flag);
}
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;
}
static struct vframe_s *get_dispbuf(u8 layer_id)
{
struct vframe_s *dispbuf = NULL;
struct video_layer_s *layer = NULL;
if (layer_id >= MAX_VD_LAYERS)
return NULL;
switch (glayer_info[layer_id].display_path_id) {
case VFM_PATH_DEF:
if (layer_id == 0 && cur_dispbuf)
dispbuf = cur_dispbuf;
else if (layer_id == 1 && cur_pipbuf)
dispbuf = cur_pipbuf;
else if (layer_id == 2 && cur_pipbuf2)
dispbuf = cur_pipbuf2;
break;
case VFM_PATH_AMVIDEO:
if (cur_dispbuf)
dispbuf = cur_dispbuf;
break;
case VFM_PATH_PIP:
if (cur_pipbuf)
dispbuf = cur_pipbuf;
break;
case VFM_PATH_PIP2:
if (cur_pipbuf2)
dispbuf = cur_pipbuf2;
break;
case VFM_PATH_VIDEO_RENDER0:
if (gvideo_recv[0] &&
gvideo_recv[0]->cur_buf)
dispbuf = gvideo_recv[0]->cur_buf;
break;
case VFM_PATH_VIDEO_RENDER1:
if (gvideo_recv[1] &&
gvideo_recv[1]->cur_buf)
dispbuf = gvideo_recv[1]->cur_buf;
break;
case VFM_PATH_VIDEO_RENDER2:
if (gvideo_recv[2] &&
gvideo_recv[2]->cur_buf)
dispbuf = gvideo_recv[2]->cur_buf;
break;
case VFM_PATH_VIDEO_RENDER5:
if (gvideo_recv_vpp[0] &&
gvideo_recv_vpp[0]->cur_buf)
dispbuf = gvideo_recv_vpp[0]->cur_buf;
break;
case VFM_PATH_VIDEO_RENDER6:
if (gvideo_recv_vpp[1] &&
gvideo_recv_vpp[1]->cur_buf)
dispbuf = gvideo_recv_vpp[1]->cur_buf;
break;
default:
break;
}
layer = get_layer_by_layer_id(layer_id);
if (layer && layer->switch_vf && layer->vf_ext)
dispbuf = layer->vf_ext;
return dispbuf;
}
#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)
{
if (type == VFRAME_EVENT_PROVIDER_UNREG) {
video_vf_unreg_provider();
drop_frame_count = 0;
receive_frame_count = 0;
display_frame_count = 0;
#ifdef AVSYNC_COUNT
avsync_count = 0;
timestamp_avsync_counter_set(avsync_count);
#endif
nn_scenes_value[0].maxprob = 0;
//init_hdr_info();
mutex_lock(&omx_mutex);
omx_continuous_drop_count = 0;
omx_continuous_drop_flag = false;
cur_disp_omx_index = 0;
dovi_drop_flag = false;
dovi_drop_frame_num = 0;
mutex_unlock(&omx_mutex);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable())
dv_vf_light_unreg_provider();
#endif
update_process_hdmi_avsync_flag(false);
} else if (type == VFRAME_EVENT_PROVIDER_RESET) {
video_vf_light_unreg_provider(1);
nn_scenes_value[0].maxprob = 0;
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
video_vf_light_unreg_provider(0);
nn_scenes_value[0].maxprob = 0;
} else if (type == VFRAME_EVENT_PROVIDER_REG) {
video_drop_vf_cnt = 0;
enable_video_discontinue_report = 1;
drop_frame_count = 0;
receive_frame_count = 0;
display_frame_count = 0;
#ifdef AVSYNC_COUNT
avsync_count = 0;
timestamp_avsync_counter_set(avsync_count);
#endif
mutex_lock(&omx_mutex);
omx_run = false;
omx_pts_set_from_hwc_count = 0;
omx_pts_set_from_hwc_count_begin = 0;
omx_check_previous_session = true;
omx_need_drop_frame_num = 0;
omx_drop_done = false;
omx_pts_set_index = 0;
omx_continusdrop_cnt = 0;
omx_continuous_drop_count = 0;
omx_continuous_drop_flag = false;
cur_disp_omx_index = 0;
dovi_drop_flag = false;
dovi_drop_frame_num = 0;
mutex_unlock(&omx_mutex);
hdmi_in_delay_maxmin_reset();
//init_hdr_info();
/* over_sync_count = 0; */
/*notify di 3d mode is frame*/
/*alternative mode,passing two buffer in one frame */
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN
if ((process_3d_type & MODE_3D_FA) &&
cur_dispbuf &&
!cur_dispbuf->trans_fmt)
vf_notify_receiver_by_name
("deinterlace",
VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE,
(void *)1);
#endif
video_vf_light_unreg_provider(0);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable())
dv_vf_light_reg_provider();
#endif
update_process_hdmi_avsync_flag(true);
} else if (type == VFRAME_EVENT_PROVIDER_FORCE_BLACKOUT) {
force_blackout = 1;
if (debug_flag & DEBUG_FLAG_BASIC_INFO) {
pr_info("%s VFRAME_EVENT_PROVIDER_FORCE_BLACKOUT\n",
__func__);
}
} else if (type == VFRAME_EVENT_PROVIDER_FR_HINT) {
#ifdef CONFIG_AM_VOUT
if (data && 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_hint(0);
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) {
vd_layer[0].property_changed = true;
vd_layer[1].property_changed = true;
}
return 0;
}
static void pip_vf_unreg_provider(void)
{
ulong flags;
int keeped = 0, ret = 0;
bool layer1_used = false;
bool layer2_used = false;
bool layer3_used = false;
u32 enabled = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
atomic_inc(&video_unreg_flag);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
ret = update_pip_recycle_buffer();
if (ret == -EAGAIN) {
/* The currently displayed vf is not added to the queue
* that needs to be released. You need to release the vf
* data in the release queue before adding the currently
* displayed vf to the release queue.
*/
release_di_buffer(1);
update_pip_recycle_buffer();
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
pipbuf_to_put[i] = NULL;
pip_rdma_buf = NULL;
#endif
if (cur_pipbuf) {
if (cur_pipbuf->vf_ext &&
IS_DI_POSTWRTIE(cur_pipbuf->type)) {
struct vframe_s *tmp =
(struct vframe_s *)cur_pipbuf->vf_ext;
memcpy(&tmp->pic_mode, &cur_pipbuf->pic_mode,
sizeof(struct vframe_pic_mode_s));
local_pip_ext = *tmp;
local_pip = *cur_pipbuf;
local_pip.vf_ext = (void *)&local_pip_ext;
} else {
local_pip = *cur_pipbuf;
}
cur_pipbuf = &local_pip;
cur_pipbuf->video_angle = 0;
}
pip_frame_count = 0;
spin_unlock_irqrestore(&lock, flags);
if (vd_layer[0].dispbuf_mapping
== &cur_pipbuf) {
layer1_used = true;
enabled |= get_video_enabled();
}
if (vd_layer[1].dispbuf_mapping
== &cur_pipbuf) {
layer2_used = true;
enabled |= get_videopip_enabled();
}
if (vd_layer[2].dispbuf_mapping
== &cur_pipbuf) {
layer3_used = true;
enabled |= get_videopip_enabled();
}
if (layer1_used || !vd_layer[0].dispbuf_mapping)
atomic_set(&primary_src_fmt, VFRAME_SIGNAL_FMT_INVALID);
if (!layer1_used && !layer2_used && !layer3_used)
cur_pipbuf = NULL;
if (blackout_pip | force_blackout) {
if (layer1_used)
safe_switch_videolayer
(0, false, false);
if (layer2_used)
safe_switch_videolayer
(1, false, false);
if (layer3_used)
safe_switch_videolayer
(2, false, false);
try_free_keep_videopip(1);
}
if (cur_pipbuf && enabled)
keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL);
else if (cur_pipbuf)
keeped = 0;
pr_info("%s: vd1 used: %s, vd2 used: %s, vd3 used: %s, keep_ret:%d, black_out:%d, cur_pipbuf:%p\n",
__func__,
layer1_used ? "true" : "false",
layer2_used ? "true" : "false",
layer3_used ? "true" : "false",
keeped, blackout_pip | force_blackout,
cur_pipbuf);
if (keeped <= 0) {/*keep failed.*/
if (keeped < 0)
pr_info("keep frame failed, disable videopip now.\n");
else
pr_info("keep frame skip, disable videopip again.\n");
if (layer1_used)
safe_switch_videolayer
(0, false, false);
if (layer2_used)
safe_switch_videolayer
(1, false, false);
if (layer3_used)
safe_switch_videolayer
(2, false, false);
try_free_keep_videopip(1);
}
/*disable_videopip = VIDEO_DISABLE_FORNEXT;*/
/*DisableVideoLayer2();*/
atomic_dec(&video_unreg_flag);
}
static void pip_vf_light_unreg_provider(int need_keep_frame)
{
ulong flags;
int ret = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
atomic_inc(&video_unreg_flag);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
ret = update_pip_recycle_buffer();
if (ret == -EAGAIN) {
/* The currently displayed vf is not added to the queue
* that needs to be released. You need to release the vf
* data in the release queue before adding the currently
* displayed vf to the release queue.
*/
release_di_buffer(1);
update_pip_recycle_buffer();
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
pipbuf_to_put[i] = NULL;
pip_rdma_buf = NULL;
#endif
if (cur_pipbuf) {
if (cur_pipbuf->vf_ext &&
IS_DI_POSTWRTIE(cur_pipbuf->type)) {
struct vframe_s *tmp =
(struct vframe_s *)cur_pipbuf->vf_ext;
memcpy(&tmp->pic_mode, &cur_pipbuf->pic_mode,
sizeof(struct vframe_pic_mode_s));
local_pip_ext = *tmp;
local_pip = *cur_pipbuf;
local_pip.vf_ext = (void *)&local_pip_ext;
} else {
local_pip = *cur_pipbuf;
}
cur_pipbuf = &local_pip;
}
spin_unlock_irqrestore(&lock, flags);
if (need_keep_frame && cur_pipbuf)
vf_keep_pip_current_locked(cur_pipbuf, NULL);
atomic_dec(&video_unreg_flag);
}
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);
videopip_drop_vf_cnt = 0;
}
return 0;
}
static void pip2_vf_unreg_provider(void)
{
ulong flags;
int keeped = 0, ret = 0;
bool layer1_used = false;
bool layer2_used = false;
bool layer3_used = false;
u32 enabled = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
atomic_inc(&video_unreg_flag);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
ret = update_pip2_recycle_buffer();
if (ret == -EAGAIN) {
/* The currently displayed vf is not added to the queue
* that needs to be released. You need to release the vf
* data in the release queue before adding the currently
* displayed vf to the release queue.
*/
release_di_buffer(2);
update_pip2_recycle_buffer();
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf2_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
pipbuf2_to_put[i] = NULL;
pip2_rdma_buf = NULL;
#endif
if (cur_pipbuf2) {
if (cur_pipbuf2->vf_ext &&
IS_DI_POSTWRTIE(cur_pipbuf2->type)) {
struct vframe_s *tmp =
(struct vframe_s *)cur_pipbuf2->vf_ext;
memcpy(&tmp->pic_mode, &cur_pipbuf2->pic_mode,
sizeof(struct vframe_pic_mode_s));
local_pip2_ext = *tmp;
local_pip2 = *cur_pipbuf2;
local_pip2.vf_ext = (void *)&local_pip2_ext;
} else {
local_pip2 = *cur_pipbuf2;
}
cur_pipbuf2 = &local_pip2;
cur_pipbuf2->video_angle = 0;
}
pip2_frame_count = 0;
spin_unlock_irqrestore(&lock, flags);
if (vd_layer[0].dispbuf_mapping
== &cur_pipbuf2) {
layer1_used = true;
enabled |= get_video_enabled();
}
if (vd_layer[1].dispbuf_mapping
== &cur_pipbuf2) {
layer2_used = true;
enabled |= get_videopip_enabled();
}
if (vd_layer[2].dispbuf_mapping
== &cur_pipbuf2) {
layer3_used = true;
enabled |= get_videopip2_enabled();
}
if (!layer1_used && !layer2_used && !layer3_used)
cur_pipbuf2 = NULL;
if (blackout_pip2 | force_blackout) {
if (layer1_used)
safe_switch_videolayer
(0, false, false);
if (layer2_used)
safe_switch_videolayer
(1, false, false);
if (layer3_used)
safe_switch_videolayer
(2, false, false);
try_free_keep_videopip2(1);
}
if (cur_pipbuf2 && enabled)
keeped = vf_keep_pip2_current_locked(cur_pipbuf2, NULL);
else if (cur_pipbuf2)
keeped = 0;
pr_info("%s: vd1 used: %s, vd2 used: %s, vd3 used: %s, keep_ret:%d, black_out:%d, cur_pipbuf2:%p\n",
__func__,
layer1_used ? "true" : "false",
layer2_used ? "true" : "false",
layer3_used ? "true" : "false",
keeped, blackout_pip2 | force_blackout,
cur_pipbuf2);
if (keeped <= 0) {/*keep failed.*/
if (keeped < 0)
pr_info("keep frame failed, disable videopip2 now.\n");
else
pr_info("keep frame skip, disable videopip2 again.\n");
if (layer1_used)
safe_switch_videolayer
(0, false, false);
if (layer2_used)
safe_switch_videolayer
(1, false, false);
if (layer3_used)
safe_switch_videolayer
(2, false, false);
try_free_keep_videopip2(1);
}
/*disable_videopip = VIDEO_DISABLE_FORNEXT;*/
/*DisableVideoLayer2();*/
atomic_dec(&video_unreg_flag);
}
static void pip2_vf_light_unreg_provider(int need_keep_frame)
{
ulong flags;
int ret = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int i;
#endif
atomic_inc(&video_unreg_flag);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
ret = update_pip2_recycle_buffer();
if (ret == -EAGAIN) {
/* The currently displayed vf is not added to the queue
* that needs to be released. You need to release the vf
* data in the release queue before adding the currently
* displayed vf to the release queue.
*/
release_di_buffer(2);
update_pip2_recycle_buffer();
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf2_to_put_num = 0;
for (i = 0; i < DISPBUF_TO_PUT_MAX; i++)
pipbuf2_to_put[i] = NULL;
pip2_rdma_buf = NULL;
#endif
if (cur_pipbuf2) {
if (cur_pipbuf2->vf_ext &&
IS_DI_POSTWRTIE(cur_pipbuf2->type)) {
struct vframe_s *tmp =
(struct vframe_s *)cur_pipbuf2->vf_ext;
memcpy(&tmp->pic_mode, &cur_pipbuf2->pic_mode,
sizeof(struct vframe_pic_mode_s));
local_pip2_ext = *tmp;
local_pip2 = *cur_pipbuf2;
local_pip2.vf_ext = (void *)&local_pip2_ext;
} else {
local_pip2 = *cur_pipbuf2;
}
cur_pipbuf2 = &local_pip2;
}
spin_unlock_irqrestore(&lock, flags);
if (need_keep_frame && cur_pipbuf2)
vf_keep_pip2_current_locked(cur_pipbuf2, NULL);
atomic_dec(&video_unreg_flag);
}
static int pip2_receiver_event_fun(int type,
void *data,
void *private_data)
{
if (type == VFRAME_EVENT_PROVIDER_UNREG) {
pip2_vf_unreg_provider();
} else if (type == VFRAME_EVENT_PROVIDER_RESET) {
pip2_vf_light_unreg_provider(1);
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
pip2_vf_light_unreg_provider(0);
} else if (type == VFRAME_EVENT_PROVIDER_REG) {
pip2_vf_light_unreg_provider(0);
videopip2_drop_vf_cnt = 0;
}
return 0;
}
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);
u32 get_blackout_pip2_policy(void)
{
return blackout_pip2 | force_blackout;
}
EXPORT_SYMBOL(get_blackout_pip2_policy);
u32 set_blackout_pip2_policy(int policy)
{
blackout_pip2 = policy;
return 0;
}
EXPORT_SYMBOL(set_blackout_pip2_policy);
u8 is_vpp_postblend(void)
{
if (cur_dev->t7_display) {
if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_POSTBLEND_EN)
return 1;
} else {
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);
void di_unreg_notify(void)
{
u32 sleep_time = 40;
while (atomic_read(&video_inirq_flag) > 0)
schedule();
if (gvideo_recv[0] && gvideo_recv[0]->active)
switch_vf(gvideo_recv[0], true);
vd_layer[0].need_switch_vf = true;
vd_layer[0].property_changed = true;
if (vinfo) {
sleep_time = vinfo->sync_duration_den * 1000;
if (vinfo->sync_duration_num) {
sleep_time /= vinfo->sync_duration_num;
/* need two vsync */
sleep_time = (sleep_time + 1) * 2;
} else {
sleep_time = 40;
}
}
msleep(sleep_time);
}
EXPORT_SYMBOL(di_unreg_notify);
/*********************************************************
* Vframe src fmt API
*********************************************************/
#define signal_color_primaries ((vf->signal_type >> 16) & 0xff)
#define signal_transfer_characteristic ((vf->signal_type >> 8) & 0xff)
#define PREFIX_SEI_NUT 39
#define SUFFIX_SEI_NUT 40
#define SEI_ITU_T_T35 4
#define ATSC_T35_PROV_CODE 0x0031
#define DVB_T35_PROV_CODE 0x003B
#define ATSC_USER_ID_CODE 0x47413934
#define DVB_USER_ID_CODE 0x00000000
#define DM_MD_USER_TYPE_CODE 0x09
static int check_media_sei(char *sei, u32 sei_size, u32 sei_type)
{
int ret = 0;
char *p;
u32 type = 0, size;
unsigned char nal_type;
unsigned char sei_payload_type = 0;
unsigned char sei_payload_size = 0;
u32 len_2094_sei = 0;
u32 country_code;
u32 provider_code;
u32 user_id;
u32 user_type_code;
if (!sei || sei_size <= 8)
return ret;
p = sei;
while (p < sei + sei_size - 8) {
size = *p++;
size = (size << 8) | *p++;
size = (size << 8) | *p++;
size = (size << 8) | *p++;
type = *p++;
type = (type << 8) | *p++;
type = (type << 8) | *p++;
type = (type << 8) | *p++;
if (((sei_type == DV_SEI || sei_type == HDR10P) &&
sei_type == type) ||
(sei_type == DV_AV1_SEI &&
sei_type == (type & 0xffff0000))) {
ret = 1;
break;
} else if ((sei_type == DV_SEI) && type == HDR10P) {
/* check DVB/ATSC as DV */
if (p >= sei + sei_size - 12)
break;
nal_type = ((*p) & 0x7E) >> 1;
if (nal_type == PREFIX_SEI_NUT) {
sei_payload_type = *(p + 2);
sei_payload_size = *(p + 3);
if (sei_payload_type == SEI_ITU_T_T35 &&
sei_payload_size >= 8) {
country_code = *(p + 4);
provider_code = (*(p + 5) << 8) |
*(p + 6);
user_id = (*(p + 7) << 24) |
(*(p + 8) << 16) |
(*(p + 9) << 8) |
(*(p + 10));
user_type_code = *(p + 11);
if (country_code == 0xB5 &&
((provider_code ==
ATSC_T35_PROV_CODE &&
user_id == ATSC_USER_ID_CODE) ||
(provider_code ==
DVB_T35_PROV_CODE &&
user_id == DVB_USER_ID_CODE)) &&
user_type_code ==
DM_MD_USER_TYPE_CODE)
len_2094_sei = sei_payload_size;
}
if (len_2094_sei > 0) {
ret = 1;
break;
}
}
}
p += size;
}
return ret;
}
static s32 clear_vframe_dovi_md_info(struct vframe_s *vf)
{
if (!vf)
return -1;
/* invalid src fmt case */
if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
return -1;
vf->src_fmt.md_size = 0;
vf->src_fmt.comp_size = 0;
vf->src_fmt.md_buf = NULL;
vf->src_fmt.comp_buf = NULL;
vf->src_fmt.parse_ret_flags = 0;
return 0;
}
s32 update_vframe_src_fmt(struct vframe_s *vf,
void *sei, u32 size, bool dual_layer,
char *prov_name, char *recv_name)
{
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
#if PARSE_MD_IN_ADVANCE
int src_fmt = -1;
int ret = 0;
#endif
#endif
int i;
char *p;
if (!vf)
return -1;
vf->src_fmt.sei_magic_code = SEI_MAGIC_CODE;
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_INVALID;
vf->src_fmt.sei_ptr = sei;
vf->src_fmt.sei_size = size;
vf->src_fmt.dual_layer = false;
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME) {
pr_info("===update vf %p, sei %p, size %d, dual_layer %d===\n",
vf, sei, size, dual_layer);
if (sei && size > 15) {
p = (char *)sei;
for (i = 0; i < size; i += 16)
pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
p[i],
p[i + 1],
p[i + 2],
p[i + 3],
p[i + 4],
p[i + 5],
p[i + 6],
p[i + 7],
p[i + 8],
p[i + 9],
p[i + 10],
p[i + 11],
p[i + 12],
p[i + 13],
p[i + 14],
p[i + 15]);
}
}
if (vf->type & VIDTYPE_MVC) {
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_MVC;
} else if (sei && size) {
if (vf->discard_dv_data) {
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("ignore nonstandard dv\n");
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
else if (dual_layer || check_media_sei(sei, size, DV_SEI) ||
check_media_sei(sei, size, DV_AV1_SEI)) {
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_DOVI;
vf->src_fmt.dual_layer = dual_layer;
#if PARSE_MD_IN_ADVANCE
if (vf->src_fmt.md_buf && vf->src_fmt.comp_buf) {
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("parse vf %p, sei %p, size %d, md_buf %p\n",
vf, sei, size, vf->src_fmt.md_buf);
ret = parse_sei_and_meta_ext
(vf, sei, size,
&vf->src_fmt.comp_size,
&vf->src_fmt.md_size,
&src_fmt,
&vf->src_fmt.parse_ret_flags,
vf->src_fmt.md_buf,
vf->src_fmt.comp_buf);
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("parse ret %d, %d, %d %d, %d\n",
ret,
src_fmt,
vf->src_fmt.md_size,
vf->src_fmt.comp_size,
vf->src_fmt.parse_ret_flags);
if (ret) {
/* mark size -1 as parser failed */
vf->src_fmt.md_size = -1;
vf->src_fmt.comp_size = -1;
}
}
#else
clear_vframe_dovi_md_info(vf);
#endif
}
#endif
}
if (vf->src_fmt.fmt == VFRAME_SIGNAL_FMT_INVALID) {
if ((signal_transfer_characteristic == 14 ||
signal_transfer_characteristic == 18) &&
signal_color_primaries == 9) {
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HLG;
} else if ((signal_transfer_characteristic == 0x30) &&
((signal_color_primaries == 9) ||
(signal_color_primaries == 2))) {
if (check_media_sei(sei, size, HDR10P))
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10PLUS;
else /* TODO: if need switch to HDR10 */
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10;
} else if ((signal_transfer_characteristic == 16) &&
((signal_color_primaries == 9) ||
(signal_color_primaries == 2))) {
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10;
} else {
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_SDR;
}
}
if (vf->src_fmt.fmt != VFRAME_SIGNAL_FMT_DOVI)
clear_vframe_dovi_md_info(vf);
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("[%s]fmt: %d\n", __func__, vf->src_fmt.fmt);
return 0;
}
EXPORT_SYMBOL(update_vframe_src_fmt);
void *get_sei_from_src_fmt(struct vframe_s *vf, u32 *sei_size)
{
if (!vf || !sei_size)
return NULL;
/* invalid src fmt case */
if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
return NULL;
*sei_size = vf->src_fmt.sei_size;
return vf->src_fmt.sei_ptr;
}
EXPORT_SYMBOL(get_sei_from_src_fmt);
enum vframe_signal_fmt_e get_vframe_src_fmt(struct vframe_s *vf)
{
if (!vf)
return VFRAME_SIGNAL_FMT_INVALID;
/* invalid src fmt case */
if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
return VFRAME_SIGNAL_FMT_INVALID;
return vf->src_fmt.fmt;
}
EXPORT_SYMBOL(get_vframe_src_fmt);
/*return 0: no parse*/
/*return 1: dovi source and parse succeeded*/
/*return 2: dovi source and parse failed*/
int get_md_from_src_fmt(struct vframe_s *vf)
{
int ret = 0;
if (!vf)
return 0;
/* invalid src fmt case */
if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE ||
vf->src_fmt.fmt != VFRAME_SIGNAL_FMT_DOVI ||
!vf->src_fmt.md_buf ||
!vf->src_fmt.comp_buf) {
ret = 0;
} else {
if (vf->src_fmt.md_size > 0)
ret = 1;
else if (vf->src_fmt.md_size == -1 &&
vf->src_fmt.comp_size == -1)
ret = 2;
}
if (debug_flag & DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("[%s] ret %d\n", __func__, ret);
return ret;
}
EXPORT_SYMBOL(get_md_from_src_fmt);
s32 clear_vframe_src_fmt(struct vframe_s *vf)
{
if (!vf)
return -1;
/* invalid src fmt case */
if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
return -1;
vf->src_fmt.sei_magic_code = 0;
vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_INVALID;
vf->src_fmt.sei_ptr = NULL;
vf->src_fmt.sei_size = 0;
vf->src_fmt.dual_layer = false;
vf->src_fmt.md_size = 0;
vf->src_fmt.comp_size = 0;
vf->src_fmt.md_buf = NULL;
vf->src_fmt.comp_buf = NULL;
vf->src_fmt.parse_ret_flags = 0;
return 0;
}
EXPORT_SYMBOL(clear_vframe_src_fmt);
/*********************************************************
* Utilities
*********************************************************/
int _video_set_disable(u32 val)
{
struct video_layer_s *layer = &vd_layer[0];
if (val > VIDEO_DISABLE_FORNEXT)
return -EINVAL;
layer->disable_video = val;
if (layer->disable_video ==
VIDEO_DISABLE_FORNEXT &&
layer->dispbuf &&
!is_local_vf(layer->dispbuf))
layer->disable_video = VIDEO_DISABLE_NONE;
if (layer->disable_video != VIDEO_DISABLE_NONE) {
pr_info("VID: VD1 off\n");
safe_switch_videolayer
(layer->layer_id, false, true);
if (layer->disable_video ==
VIDEO_DISABLE_FORNEXT &&
layer->dispbuf &&
!is_local_vf(layer->dispbuf))
layer->property_changed = true;
/* FIXME */
if (layer->keep_frame_id == 2)
try_free_keep_videopip2(0);
else if (layer->keep_frame_id == 1)
try_free_keep_videopip(0);
else if (layer->keep_frame_id == 0)
try_free_keep_video(0);
} else {
if (layer->dispbuf &&
!is_local_vf(layer->dispbuf)) {
safe_switch_videolayer
(layer->layer_id, true, true);
pr_info("VID: VD1 on\n");
layer->property_changed = true;
}
}
return 0;
}
void video_set_global_output(u32 index, u32 val)
{
if (index == 0) {
if (val != 0)
vd_layer[0].global_output = 1;
else
vd_layer[0].global_output = 0;
} else if (index == 1) {
if (vd_layer[1].vpp_index == VPP0) {
if (val != 0)
vd_layer[1].global_output = 1;
else
vd_layer[1].global_output = 0;
} else if (vd_layer_vpp[0].layer_id == index &&
vd_layer_vpp[0].vpp_index == VPP1) {
if (val != 0)
vd_layer_vpp[0].global_output = 1;
else
vd_layer_vpp[0].global_output = 0;
} else if (vd_layer_vpp[1].layer_id == index &&
vd_layer_vpp[1].vpp_index == VPP2) {
if (val != 0)
vd_layer_vpp[1].global_output = 1;
else
vd_layer_vpp[1].global_output = 0;
}
} else if (index == 2) {
if (vd_layer[2].vpp_index == VPP0) {
if (val != 0)
vd_layer[2].global_output = 1;
else
vd_layer[2].global_output = 0;
} else if (vd_layer_vpp[0].layer_id == index &&
vd_layer_vpp[0].vpp_index == VPP1) {
if (val != 0)
vd_layer_vpp[0].global_output = 1;
else
vd_layer_vpp[0].global_output = 0;
} else if (vd_layer_vpp[1].layer_id == index &&
vd_layer_vpp[1].vpp_index == VPP2) {
if (val != 0)
vd_layer_vpp[1].global_output = 1;
else
vd_layer_vpp[1].global_output = 0;
}
}
pr_info("VID: VD%d set global output as %d\n",
index + 1, (val != 0) ? 1 : 0);
}
u32 video_get_layer_capability(void)
{
return layer_cap;
}
#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;
bool updateomxpts;
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 %dsession=0x%x\n",
tmp_pts, omx_cur_session);
omx_pts_set_index = 0;
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 (set_from_hwc == 1) {
if (frame_num >= cur_disp_omx_index) {
omx_continuous_drop_flag = false;
omx_continuous_drop_count = 0;
} else {
if (omx_continuous_drop_flag &&
(debug_flag &
DEBUG_FLAG_OMX_DEBUG_DROP_FRAME))
pr_info("ignore previous rendered frame %d\n",
frame_num);
}
} else {
omx_continuous_drop_count++;
if (omx_continuous_drop_count >=
OMX_CONTINUOUS_DROP_LEVEL &&
!(debug_flag &
DEBUG_FLAG_OMX_DISABLE_DROP_FRAME)) {
omx_continuous_drop_flag = true;
if (debug_flag & DEBUG_FLAG_OMX_DEBUG_DROP_FRAME)
pr_info("countinous drop %d\n",
omx_continuous_drop_count);
}
}
if (not_reset == 0) {
updateomxpts = set_from_hwc;
if (!set_from_hwc) {
omx_continusdrop_cnt++;
if (omx_continusdrop_cnt > 1) {
/* continus drop update omx_pts */
updateomxpts = true;
} else {
struct vframe_s *vf = NULL;
vf = vf_peek(RECEIVER_NAME);
if (vf && vf->omx_index > 0 &&
omx_pts_set_index > vf->omx_index)
omx_pts_set_index = vf->omx_index - 1;
}
} else {
omx_continusdrop_cnt = 0;
}
if (updateomxpts) {
time_setomxpts_last = time_setomxpts;
time_setomxpts = sched_clock();
omx_pts = tmp_pts;
ATRACE_COUNTER("omxpts", omx_pts);
}
}
/* kodi may render first frame, then drop dozens of frames */
if (set_from_hwc == 0 && omx_run &&
frame_num <= 2 && not_reset == 0 &&
omx_pts_set_from_hwc_count > 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 %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++;
if (omx_pts_set_from_hwc_count_begin <
OMX_MAX_COUNT_RESET_SYSTEMTIME_BEGIN)
omx_pts_set_from_hwc_count_begin++;
} else if (set_from_hwc == 0 && !omx_run) {
struct vframe_s *vf = NULL;
while (try_cnt--) {
vf = vf_peek(RECEIVER_NAME);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable() &&
vf && is_dovi_frame(vf)) {
if (debug_flag &
DEBUG_FLAG_OMX_DV_DROP_FRAME)
pr_info("dovi will drop %d in vsync\n",
frame_num);
dovi_drop_flag = true;
dovi_drop_frame_num = frame_num;
if (disable_dv_drop) {
omx_run = true;
dovi_drop_flag = false;
dovi_drop_frame_num = 0;
omx_drop_done = true;
}
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;
}
}
}
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;
}
} else if (layer_id == 2) {
if (layer_cap & LAYER2_BUSY) {
ret = -EBUSY;
} else if (layer_cap & LAYER2_AVAIL) {
ret = 0;
layer_cap |= LAYER2_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;
}
} else if (layer_id == 2) {
if ((layer_cap & LAYER2_BUSY) &&
(layer_cap & LAYER2_AVAIL)) {
ret = 0;
layer_cap &= ~LAYER2_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:
case AMSTREAM_IOC_GET_PIP_DISPLAYPATH:
case AMSTREAM_IOC_SET_PIP_DISPLAYPATH:
layer = &glayer_info[1];
break;
case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP2_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP2_OUTPUT:
case AMSTREAM_IOC_GET_VIDEOPIP2_DISABLE:
case AMSTREAM_IOC_SET_VIDEOPIP2_DISABLE:
case AMSTREAM_IOC_GET_VIDEOPIP2_AXIS:
case AMSTREAM_IOC_SET_VIDEOPIP2_AXIS:
case AMSTREAM_IOC_GET_VIDEOPIP2_CROP:
case AMSTREAM_IOC_SET_VIDEOPIP2_CROP:
case AMSTREAM_IOC_GET_PIP2_SCREEN_MODE:
case AMSTREAM_IOC_SET_PIP2_SCREEN_MODE:
case AMSTREAM_IOC_GET_PIP2_ZORDER:
case AMSTREAM_IOC_SET_PIP2_ZORDER:
case AMSTREAM_IOC_GET_PIP2_DISPLAYPATH:
case AMSTREAM_IOC_SET_PIP2_DISPLAYPATH:
layer = &glayer_info[2];
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 states;
ret = -EFAULT;
memset(&states, 0, sizeof(struct vframe_states));
if (video_vf_get_states(&states) == 0)
if (copy_to_user(argp,
&states, sizeof(states)) == 0)
ret = 0;
}
break;
case AMSTREAM_IOC_GET_VIDEOPIP2_DISABLE:
put_user(vd_layer[2].disable_video, (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE:
put_user(vd_layer[1].disable_video, (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_VIDEO_DISABLE:
put_user(vd_layer[0].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(VD2_PATH, val);
else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_SET_VIDEOPIP2_DISABLE:
{
u32 val;
if (copy_from_user(&val, argp, sizeof(u32)) == 0)
ret = _videopip_set_disable(VD3_PATH, 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_VIDEOPIP2_AXIS:
case AMSTREAM_IOC_GET_VIDEO_AXIS:
{
int axis[4];
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_VIDEOPIP2_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_VIDEOPIP2_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_VIDEOPIP2_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_PIP2_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_PIP2_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) {
u8 id = layer->layer_id;
layer->wide_mode = mode;
vd_layer[id].property_changed = true;
}
} 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_GET_BLACKOUT_PIP2_POLICY:
if (copy_to_user(argp, &blackout_pip2, 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_SET_BLACKOUT_PIP2_POLICY:{
u32 mode;
if (copy_from_user(&mode, argp, sizeof(u32)) == 0) {
if (mode > 2)
ret = -EINVAL;
else
blackout_pip2 = 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);
if (cur_dispbuf != &vf_local)
cur_dispbuf = NULL;
spin_unlock_irqrestore(&lock, flags);
}
break;
case AMSTREAM_IOC_CLEAR_VIDEO:
if (blackout)
safe_switch_videolayer(0, false, false);
break;
case AMSTREAM_IOC_CLEAR_PIP_VBUF:{
unsigned long flags;
while (atomic_read(&video_inirq_flag) > 0 ||
atomic_read(&video_unreg_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
if (cur_pipbuf != &local_pip)
cur_pipbuf = NULL;
spin_unlock_irqrestore(&lock, flags);
}
break;
case AMSTREAM_IOC_CLEAR_PIP2_VBUF:{
unsigned long flags;
while (atomic_read(&video_inirq_flag) > 0 ||
atomic_read(&video_unreg_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
if (cur_pipbuf2 != &local_pip2)
cur_pipbuf2 = NULL;
spin_unlock_irqrestore(&lock, flags);
}
break;
case AMSTREAM_IOC_CLEAR_VIDEOPIP:
safe_switch_videolayer(1, false, false);
break;
case AMSTREAM_IOC_CLEAR_VIDEOPIP2:
safe_switch_videolayer(2, false, false);
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;
struct vframe_s *dispbuf = NULL;
if (type != process_3d_type) {
process_3d_type = type;
if (mvc_flag)
process_3d_type |= MODE_3D_MVC;
vd_layer[0].property_changed = true;
dispbuf = get_dispbuf(0);
if ((process_3d_type & MODE_3D_FA) &&
dispbuf &&
!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)
{
u32 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_VIDEOPIP2_OUTPUT:
case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT:
video_set_global_output(layer->layer_id, arg ? 1 : 0);
break;
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP2_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT:
if (layer->layer_id == 0)
put_user(vd_layer[0].global_output, (u32 __user *)argp);
else if (layer->layer_id == 1)
put_user(vd_layer[1].global_output, (u32 __user *)argp);
else if (layer->layer_id == 2)
put_user(vd_layer[2].global_output, (u32 __user *)argp);
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) -
vd_layer[0].onoff_time;
if (vd_layer[0].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(vd_layer[0].onoff_state, (u32 __user *)argp);
break;
}
case AMSTREAM_IOC_SET_TUNNEL_MODE: {
u32 tunnelmode = 0;
if (copy_from_user(&tunnelmode, argp, sizeof(u32)) == 0)
tsync_set_tunnel_mode(tunnelmode);
else
ret = -EFAULT;
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_PIP2_ZORDER:
case AMSTREAM_IOC_GET_ZORDER:
put_user(layer->zorder, (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_PIP_ZORDER:
case AMSTREAM_IOC_SET_PIP2_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)
vd_layer[0].property_changed = true;
else if ((layer->layer_id == 1) && new_prop)
vd_layer[1].property_changed = true;
} else {
ret = -EFAULT;
}
}
break;
case AMSTREAM_IOC_GET_DISPLAYPATH:
case AMSTREAM_IOC_GET_PIP_DISPLAYPATH:
case AMSTREAM_IOC_GET_PIP2_DISPLAYPATH:
put_user(layer->display_path_id, (s32 __user *)argp);
break;
case AMSTREAM_IOC_SET_DISPLAYPATH:
case AMSTREAM_IOC_SET_PIP_DISPLAYPATH:
case AMSTREAM_IOC_SET_PIP2_DISPLAYPATH:{
u32 path_id, new_prop = 0;
if (copy_from_user(&path_id, argp, sizeof(s32)) == 0) {
if (layer->display_path_id != path_id) {
new_prop = 1;
pr_info
("VID: VD%d, path_id changed %d->%d\n",
layer->layer_id + 1,
layer->display_path_id,
path_id);
}
layer->display_path_id = path_id;
if (layer->layer_id == 0 && new_prop)
vd_layer[0].property_changed = true;
else if ((layer->layer_id == 1) && new_prop)
vd_layer[1].property_changed = true;
else if ((layer->layer_id == 2) && new_prop)
vd_layer[2].property_changed = true;
} 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_GET_DISPLAYPATH:
case AMSTREAM_IOC_SET_DISPLAYPATH:
case AMSTREAM_IOC_GET_PIP_DISPLAYPATH:
case AMSTREAM_IOC_SET_PIP_DISPLAYPATH:
case AMSTREAM_IOC_QUERY_LAYER:
case AMSTREAM_IOC_ALLOC_LAYER:
case AMSTREAM_IOC_FREE_LAYER:
case AMSTREAM_IOC_GET_PIP2_DISPLAYPATH:
case AMSTREAM_IOC_SET_PIP2_DISPLAYPATH:
case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP2_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP2_OUTPUT:
case AMSTREAM_IOC_GET_VIDEOPIP2_DISABLE:
case AMSTREAM_IOC_SET_VIDEOPIP2_DISABLE:
case AMSTREAM_IOC_GET_VIDEOPIP2_AXIS:
case AMSTREAM_IOC_SET_VIDEOPIP2_AXIS:
case AMSTREAM_IOC_GET_VIDEOPIP2_CROP:
case AMSTREAM_IOC_SET_VIDEOPIP2_CROP:
case AMSTREAM_IOC_GET_PIP2_SCREEN_MODE:
case AMSTREAM_IOC_SET_PIP2_SCREEN_MODE:
case AMSTREAM_IOC_GET_PIP2_ZORDER:
case AMSTREAM_IOC_SET_PIP2_ZORDER:
arg = (unsigned long)compat_ptr(arg);
return amvideo_ioctl(file, cmd, 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_SET_TUNNEL_MODE:
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)
{
u32 val = 0;
poll_wait(file, &amvideo_prop_change_wait, wait_table);
val = atomic_read(&video_prop_change);
if (val) {
atomic_set(&status_changed, val);
atomic_set(&video_prop_change, 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 void parse_param_to_char(char *buf_orig, char **parm)
{
char *ps, *token;
unsigned int n = 0;
char delim1[3] = " ";
char delim2[2] = "\n";
ps = buf_orig;
strcat(delim1, delim2);
while (1) {
token = strsep(&ps, delim1);
if (!token)
break;
if (*token == '\0')
continue;
parm[n++] = token;
}
}
static void int_convert_str(int num, char cur_s[], int bit_chose)
{
char buf[SCENES_CUR_USE_VALUE] = {0};
int i, count, cur_s_len;
if (bit_chose == 10)
snprintf(buf, sizeof(buf), "%d", num);
else if (bit_chose == 16)
snprintf(buf, sizeof(buf), "%x", num);
count = strlen(buf);
cur_s_len = strlen(cur_s);
buf[count] = ' ';
for (i = 0; i < count + 1; i++)
cur_s[i + cur_s_len] = buf[i];
}
static void str_sapr_conv(const char *s, unsigned int size, int *dest, int num)
{
int i, j;
char *s1;
const char *end;
unsigned int len;
long value;
if (size <= 0 || !s)
return;
s1 = kmalloc(size + 1, GFP_KERNEL);
if (!s1)
return;
//len = sizeof(s);
len = size * num;
end = s;
j = 0;
while (len >= size) {
for (i = 0; i < size; i++)
s1[i] = end[i];
s1[size] = '\0';
if (kstrtoul(s1, 10, &value) < 0)
break;
*dest++ = value;
end = end + size;
len -= size;
j++;
if (j >= num)
break;
}
kfree(s1);
}
static ssize_t video_3d_scale_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;
vd_layer[0].property_changed = true;
amlog_mask
(LOG_MASK_SYSFS,
"%s:%s 3d scale.\n", __func__,
enable ? "enable" : "disable");
#endif
return count;
}
static ssize_t video_sr_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "super_scaler:%d\n", super_scaler);
}
static ssize_t video_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;
vd_layer[0].property_changed = true;
}
}
mutex_unlock(&video_module_mutex);
return strnlen(buf, count);
}
static ssize_t video_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 video_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_axis_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
int x, y, w, h;
struct disp_info_s *layer = &glayer_info[0];
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 video_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 video_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 video_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];
vd_layer[0].property_changed = true;
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 video_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 video_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;
vd_layer[0].property_changed = true;
}
return count;
}
static ssize_t video_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-V",
"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", "non-linear-T"
};
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 video_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;
vd_layer[0].property_changed = true;
}
return count;
}
static ssize_t video_blackout_policy_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", blackout);
}
static ssize_t video_blackout_policy_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(buf, 0, &blackout);
if (r < 0)
return -EINVAL;
if (debug_flag & DEBUG_FLAG_BASIC_INFO)
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 = kstrtouint(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 video_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 video_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) {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y +
cur_dev->vpp_off, val, 8, 9);
#endif
} 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 video_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 video_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) {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y +
cur_dev->vpp_off, val, 8, 9);
#endif
} 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 video_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 video_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 video_test_screen_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "0x%x\n", test_screen);
}
/* [24] Flag: enable/disable auto background color */
/* [23:16] Y */
/* [15: 8] Cb */
/* [ 7: 0] Cr */
static ssize_t video_background_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "channel_bg(0x%x) no_channel_bg(0x%x)\n",
vd_layer[0].video_en_bg_color,
vd_layer[0].video_dis_bg_color);
}
static ssize_t video_rgb_screen_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "0x%x\n", rgb_screen);
}
static ssize_t enable_hdmi_delay_check_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", enable_hdmi_delay_normal_check);
}
static ssize_t enable_hdmi_delay_check_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;
enable_hdmi_delay_normal_check = value >= 0 ? (u8)value : 0;
return count;
}
static ssize_t hdmi_delay_debug_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", hdmin_delay_count_debug);
}
#define SCALE 6
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
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;
}
#endif
/* 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 + 113 * b + 128) >> 8) + 128;
v = ((112 * r - 102 * g - 10 * b + 128) >> 8) + 128;
return (y << 16) | (u << 8) | v;
}
static ssize_t video_test_screen_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
unsigned int data = 0x0;
r = kstrtouint(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);
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
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));
#endif
else
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
test_screen & 0x00ffffff);
if (debug_flag & DEBUG_FLAG_BASIC_INFO) {
pr_info("%s write(VPP_MISC,%x) write(VPP_DUMMY_DATA1, %x)\n",
__func__, data, test_screen & 0x00ffffff);
}
return count;
}
/* [24] Flag: enable/disable auto background color */
/* [23:16] Y */
/* [15: 8] Cb */
/* [ 7: 0] Cr */
static ssize_t video_background_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)) {
pr_info("video bg color, channel(0x%x) no_channel(0x%x)\n",
parsed[0], parsed[1]);
vd_layer[0].video_en_bg_color = parsed[0];
vd_layer[0].video_dis_bg_color = parsed[1];
} else {
pr_err("video_background: wrong input params\n");
return -EINVAL;
}
return count;
}
static ssize_t video_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 = kstrtouint(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()) {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
rgb_screen & 0x00ffffff);
#endif
} 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_BASIC_INFO) {
pr_info("%s write(VPP_DUMMY_DATA1, %x)\n",
__func__, rgb_screen & 0x00ffffff);
}
return count;
}
static ssize_t video_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 video_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 = kstrtouint(buf, 0, &factor);
if (r < 0)
return -EINVAL;
if (vpp_set_nonlinear_factor(layer, factor) == 0)
vd_layer[0].property_changed = true;
return count;
}
static ssize_t video_nonlinear_t_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_t_factor(layer);
return sprintf(buf, "%d\n", factor);
}
static ssize_t video_nonlinear_t_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 = kstrtouint(buf, 0, &factor);
if (r < 0)
return -EINVAL;
if (vpp_set_nonlinear_t_factor(layer, factor) == 0)
vd_layer[0].property_changed = true;
return count;
}
static ssize_t video_disable_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n",
vd_layer[0].disable_video);
}
static ssize_t video_disable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int val;
if (debug_flag & DEBUG_FLAG_BASIC_INFO)
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", vd_layer[0].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 = kstrtouint(buf, 0, &vd_layer[0].global_output);
if (r < 0)
return -EINVAL;
pr_info("%s(%d)\n", __func__, vd_layer[0].global_output);
return count;
}
static ssize_t video_hold_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", hold_video);
}
static ssize_t video_hold_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int value;
cur_width = 0;
cur_height = 0;
if (debug_flag & DEBUG_FLAG_BASIC_INFO)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
while (atomic_read(&video_inirq_flag) > 0)
schedule();
if (value == 0 && hold_video == 1)
hold_property_changed = 1;
hold_video = value;
return count;
}
static ssize_t video_freerun_mode_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", freerun_mode);
}
static ssize_t video_freerun_mode_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(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_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_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;
struct vframe_s *dispbuf = NULL;
r = kstrtouint(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;
vd_layer[0].property_changed = true;
dispbuf = get_dispbuf(0);
if ((process_3d_type & MODE_3D_FA) &&
dispbuf && !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];
struct vframe_s *dispbuf = NULL;
unsigned int canvas0Addr;
dispbuf = get_dispbuf(0);
if (dispbuf) {
canvas0Addr = get_layer_display_canvas(0);
canvas_read(canvas0Addr & 0xff, &canvas);
addr[0] = canvas.addr;
canvas_read((canvas0Addr >> 8) & 0xff, &canvas);
addr[1] = canvas.addr;
canvas_read((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 hdmin_delay_start_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", hdmin_delay_start);
}
static ssize_t hdmin_delay_start_store(struct class *class,
struct class_attribute *attr,
const char *buf,
size_t count)
{
int r;
int value;
unsigned long flags;
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
spin_lock_irqsave(&hdmi_avsync_lock, flags);
hdmin_delay_start = value;
hdmin_delay_start_time = -1;
pr_info("[%s] hdmin_delay_start:%d\n", __func__, value);
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
return count;
}
static ssize_t hdmin_delay_min_ms_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", hdmin_delay_min_ms);
}
static ssize_t hdmin_delay_min_ms_store(struct class *class,
struct class_attribute *attr,
const char *buf,
size_t count)
{
int r;
int value;
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
hdmin_delay_min_ms = value;
pr_info("[%s] hdmin_delay_min_ms:%d\n", __func__, value);
return count;
}
static ssize_t hdmin_delay_max_ms_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", hdmin_delay_max_ms);
}
static ssize_t hdmin_delay_max_ms_store(struct class *class,
struct class_attribute *attr,
const char *buf,
size_t count)
{
int r;
int value;
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
hdmin_delay_max_ms = value;
pr_info("[%s] hdmin_delay_max_ms:%d\n", __func__, value);
return count;
}
static ssize_t hdmin_delay_duration_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", last_required_total_delay);
}
/*set video total delay*/
static ssize_t hdmin_delay_duration_store(struct class *class,
struct class_attribute *attr,
const char *buf,
size_t count)
{
int r;
int value;
unsigned long flags;
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
if (value < 0) { /*not support*/
pr_info("[%s] invalid delay: %d\n", __func__, value);
return -EINVAL;
}
spin_lock_irqsave(&hdmi_avsync_lock, flags);
last_required_total_delay = value;
spin_unlock_irqrestore(&hdmi_avsync_lock, flags);
pr_info("[%s]current delay %d, total require %d\n",
__func__, vframe_walk_delay, last_required_total_delay);
return count;
}
static ssize_t vframe_walk_delay_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", vframe_walk_delay);
}
static ssize_t last_required_total_delay_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", last_required_total_delay);
}
static ssize_t frame_canvas_width_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
struct vframe_s *dispbuf = NULL;
struct canvas_s canvas;
u32 width[3];
unsigned int canvas0Addr;
dispbuf = get_dispbuf(0);
if (dispbuf) {
canvas0Addr = get_layer_display_canvas(0);
canvas_read(canvas0Addr & 0xff, &canvas);
width[0] = canvas.width;
canvas_read((canvas0Addr >> 8) & 0xff, &canvas);
width[1] = canvas.width;
canvas_read((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 vframe_s *dispbuf = NULL;
struct canvas_s canvas;
u32 height[3];
unsigned int canvas0Addr;
dispbuf = get_dispbuf(0);
if (dispbuf) {
canvas0Addr = get_layer_display_canvas(0);
canvas_read(canvas0Addr & 0xff, &canvas);
height[0] = canvas.height;
canvas_read((canvas0Addr >> 8) & 0xff, &canvas);
height[1] = canvas.height;
canvas_read((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)
{
struct vframe_s *dispbuf = NULL;
dispbuf = get_dispbuf(0);
if (hold_video == 1 &&
(glayer_info[0].display_path_id ==
VFM_PATH_AMVIDEO ||
glayer_info[0].display_path_id ==
VFM_PATH_DEF))
return sprintf(buf, "%d\n", cur_width);
if (dispbuf) {
if (dispbuf->type & VIDTYPE_COMPRESS)
return sprintf(buf, "%d\n", dispbuf->compWidth);
else
return sprintf(buf, "%d\n", dispbuf->width);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_height_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
struct vframe_s *dispbuf = NULL;
if (hold_video == 1 &&
(glayer_info[0].display_path_id ==
VFM_PATH_AMVIDEO ||
glayer_info[0].display_path_id ==
VFM_PATH_DEF))
return sprintf(buf, "%d\n", cur_height);
dispbuf = get_dispbuf(0);
if (dispbuf) {
if (dispbuf->type & VIDTYPE_COMPRESS)
return sprintf(buf, "%d\n", dispbuf->compHeight);
else
return sprintf(buf, "%d\n", dispbuf->height);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_format_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
struct vframe_s *dispbuf = NULL;
ssize_t ret = 0;
dispbuf = get_dispbuf(0);
if (dispbuf) {
if ((dispbuf->type & VIDTYPE_TYPEMASK) ==
VIDTYPE_INTERLACE_TOP)
ret = sprintf(buf, "interlace-top\n");
else if ((dispbuf->type & VIDTYPE_TYPEMASK) ==
VIDTYPE_INTERLACE_BOTTOM)
ret = sprintf(buf, "interlace-bottom\n");
else
ret = sprintf(buf, "progressive\n");
if (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)
{
struct vframe_s *dispbuf = NULL;
dispbuf = get_dispbuf(0);
if (dispbuf) {
u32 ar = (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",
(dispbuf->width << 8) /
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;
memset(&states, 0, sizeof(struct vframe_states));
if (video_vf_get_states(&states) == 0) {
ret += sprintf(buf + ret, "amvideo vframe states\n");
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);
ret += sprintf(buf + ret,
"vf type_original=%d\n",
vf->type_original);
if (vf->type & VIDTYPE_COMPRESS) {
ret += sprintf(buf + ret,
"vf compHeadAddr=%lx\n",
vf->compHeadAddr);
ret += sprintf(buf + ret,
"vf compBodyAddr =%lx\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=%lx(%ld)\n",
canvas_get_addr
(canvasY(vf->canvas0Addr)),
canvas_get_addr
(canvasY(vf->canvas0Addr)));
ret += sprintf(buf + ret,
"vf canvas0Adr.uv.adr=%lx(%ld)\n",
canvas_get_addr
(canvasUV(vf->canvas0Addr)),
canvas_get_addr
(canvasUV(vf->canvas0Addr)));
}
if (vf->vf_ext)
ret += sprintf(buf + ret,
"vf_ext=%p\n",
vf->vf_ext);
}
spin_unlock_irqrestore(&lock, flags);
} else {
spin_lock_irqsave(&lock, flags);
vf = get_dispbuf(0);
if (vf) {
ret += sprintf(buf + ret,
"vd_layer[0] vframe states\n");
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);
ret += sprintf(buf + ret,
"vf type_original=%d\n",
vf->type_original);
if (vf->type & VIDTYPE_COMPRESS) {
ret += sprintf(buf + ret,
"vf compHeadAddr=%lx\n",
vf->compHeadAddr);
ret += sprintf(buf + ret,
"vf compBodyAddr =%lx\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=%lx(%ld)\n",
canvas_get_addr
(canvasY(vf->canvas0Addr)),
canvas_get_addr
(canvasY(vf->canvas0Addr)));
ret += sprintf(buf + ret,
"vf canvas0Adr.uv.adr=%lx(%ld)\n",
canvas_get_addr
(canvasUV(vf->canvas0Addr)),
canvas_get_addr
(canvasUV(vf->canvas0Addr)));
}
if (vf->vf_ext)
ret += sprintf(buf + ret,
"vf_ext=%p\n",
vf->vf_ext);
} else {
ret += sprintf(buf + ret, "vframe no states\n");
}
spin_unlock_irqrestore(&lock, flags);
}
return ret;
}
#ifdef CONFIG_AM_VOUT
static ssize_t device_resolution_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
const struct vinfo_s *info = get_current_vinfo();
if (info)
return sprintf(buf, "%dx%d\n", info->width, info->height);
else
return sprintf(buf, "0x0\n");
}
#endif
static ssize_t video_filename_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", file_name);
}
static ssize_t video_filename_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 video_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 video_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 = kstrtouint(buf, 0, &s_value);
if (r < 0)
return -EINVAL;
trickmode_duration = s_value * 9000;
return count;
}
static ssize_t video_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 video_vsync_pts_inc_upint_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(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 = kstrtouint(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 video_vsync_slow_factor_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", vsync_slow_factor);
}
static ssize_t video_vsync_slow_factor_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(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;
struct vframe_states states;
states.buf_avail_num = 0;
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", vd_layer[0].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 video_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 video_angle_store(struct class *cla,
struct class_attribute *attr, const char *buf,
size_t count)
{
int r;
u32 s_value;
r = kstrtouint(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 video_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_BASIC_INFO)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (val == 1) {
if (vd_layer[0].keep_frame_id == 2)
try_free_keep_videopip2(1);
if (vd_layer[0].keep_frame_id == 1)
try_free_keep_videopip(1);
else if (vd_layer[0].keep_frame_id == 0)
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;
struct vframe_s *dispbuf = NULL;
dispbuf = get_dispbuf(0);
if (dispbuf) {
u32 adapted_mode = (dispbuf->ratio_control
& DISP_RATIO_ADAPTED_PICMODE) ? 1 : 0;
u32 info_frame = (dispbuf->ratio_control
& DISP_RATIO_INFOFRAME_AVAIL) ? 1 : 0;
ret += sprintf(buf + ret, "ratio_control=0x%x\n",
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",
dispbuf->pic_mode.hs,
dispbuf->pic_mode.he,
dispbuf->pic_mode.vs,
dispbuf->pic_mode.ve);
ret += sprintf(buf + ret, "screen_mode=%d\n",
dispbuf->pic_mode.screen_mode);
ret += sprintf(buf + ret, "custom_ar=%d\n",
dispbuf->pic_mode.custom_ar);
ret += sprintf(buf + ret, "AFD_enable=%d\n",
dispbuf->pic_mode.AFD_enable);
return ret;
}
return sprintf(buf, "NA\n");
}
static ssize_t src_fmt_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
int ret = 0;
struct vframe_s *dispbuf = NULL;
enum vframe_signal_fmt_e fmt;
void *sei_ptr;
u32 sei_size = 0;
dispbuf = get_dispbuf(0);
ret += sprintf(buf + ret, "vd1 dispbuf: %p\n", dispbuf);
if (dispbuf) {
fmt = get_vframe_src_fmt(dispbuf);
if (fmt != VFRAME_SIGNAL_FMT_INVALID) {
sei_ptr = get_sei_from_src_fmt(dispbuf, &sei_size);
ret += sprintf(buf + ret, "fmt = %s\n",
src_fmt_str[fmt]);
ret += sprintf(buf + ret, "sei: %p, size: %d\n",
sei_ptr, sei_size);
} else {
ret += sprintf(buf + ret, "src_fmt is invalid\n");
}
}
dispbuf = get_dispbuf(1);
ret += sprintf(buf + ret, "vd2 dispbuf: %p\n", dispbuf);
if (dispbuf) {
fmt = get_vframe_src_fmt(dispbuf);
if (fmt != VFRAME_SIGNAL_FMT_INVALID) {
sei_size = 0;
sei_ptr = get_sei_from_src_fmt(dispbuf, &sei_size);
ret += sprintf(buf + ret, "fmt=0x%s\n",
src_fmt_str[fmt]);
ret += sprintf(buf + ret, "sei: %p, size: %d\n",
sei_ptr, sei_size);
} else {
ret += sprintf(buf + ret, "src_fmt is invalid\n");
}
}
return ret;
}
static ssize_t process_fmt_show
(struct class *cla, struct class_attribute *attr, char *buf)
{
int ret = 0;
struct vframe_s *dispbuf = NULL;
enum vframe_signal_fmt_e fmt;
char process_name[MAX_VD_LAYER][32];
char output_fmt[32];
bool dolby_on = false;
bool hdr_bypass = false;
int l;
static const char * const fmt_str[] = {
"SDR", "HDR10", "HDR10+", "HDR Prime", "HLG",
"Dolby Vison", "Dolby Vison Low latency", "MVC"
};
dolby_on = is_dolby_vision_on();
dispbuf = get_dispbuf(0);
if (dispbuf) {
fmt = get_vframe_src_fmt(dispbuf);
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
ret += sprintf(buf + ret, "vd1: src_fmt = %s; ",
fmt_str[fmt]);
else
ret += sprintf(buf + ret, "vd1: src_fmt = null; ");
get_hdr_process_name(0, process_name[0], output_fmt);
l = strlen("HDR_BYPASS");
if (!strncmp(process_name[0], "HDR_BYPASS", l) ||
!strncmp(process_name[0], "HLG_BYPASS", l))
hdr_bypass = true;
if (dolby_on) {
ret += sprintf(buf + ret, "out_fmt = IPT\n");
} else if (hdr_bypass) {
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
if ((!strcmp(fmt_str[fmt], "HDR10") ||
!strcmp(fmt_str[fmt], "HDR10+")) &&
(!strcmp(output_fmt, "HDR") ||
!strcmp(output_fmt, "HDR+")))
ret += sprintf(buf + ret,
"out_fmt = %s_%s\n",
fmt_str[fmt], output_fmt);
else
ret += sprintf(buf + ret,
"out_fmt = %s\n", fmt_str[fmt]);
else
ret += sprintf(buf + ret, "out_fmt = src!\n");
} else {
ret += sprintf(buf + ret, "process = %s\n",
process_name[0]);
}
}
hdr_bypass = false;
dispbuf = get_dispbuf(1);
if (dispbuf) {
fmt = get_vframe_src_fmt(dispbuf);
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
ret += sprintf(buf + ret, "vd2: src_fmt = %s; ",
fmt_str[fmt]);
else
ret += sprintf(buf + ret, "vd2: src_fmt = null; ");
get_hdr_process_name(1, process_name[1], output_fmt);
l = strlen("HDR_BYPASS");
if (!strncmp(process_name[1], "HDR_BYPASS", l) ||
!strncmp(process_name[1], "HLG_BYPASS", l))
hdr_bypass = true;
if (dolby_on) {
ret += sprintf(buf + ret, "out_fmt = IPT\n");
} else if (hdr_bypass) {
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
if ((!strcmp(fmt_str[fmt], "HDR10") ||
!strcmp(fmt_str[fmt], "HDR10+")) &&
(!strcmp(output_fmt, "HDR") ||
!strcmp(output_fmt, "HDR+")))
ret += sprintf(buf + ret,
"out_fmt = %s_%s\n",
fmt_str[fmt], output_fmt);
else
ret += sprintf(buf + ret,
"out_fmt = %s\n", fmt_str[fmt]);
else
ret += sprintf(buf + ret, "out_fmt = src!\n");
} else {
ret += sprintf(buf + ret, "process = %s\n",
process_name[1]);
}
}
return ret;
}
static ssize_t cur_aipq_sp_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
ssize_t count = 0;
if (!cur_dispbuf)
return 0;
count += sprintf(buf + count, "top_one:%d\n", scene_prob[0]);
count += sprintf(buf + count, "top_one_prob:%d\n", scene_prob[1]);
count += sprintf(buf + count, "cur_skin_pct:%d\n",
aipq_hist_data.cur_skin_pct);
count += sprintf(buf + count, "cur_green_pct:%d\n",
aipq_hist_data.cur_green_pct);
count += sprintf(buf + count, "cur_blue_pct:%d\n",
aipq_hist_data.cur_blue_pct);
count += sprintf(buf + count, "pre_skin_pct:%d\n",
aipq_hist_data.pre_skin_pct);
count += sprintf(buf + count, "pre_green_pct:%d\n",
aipq_hist_data.pre_green_pct);
count += sprintf(buf + count, "pre_blue_pct:%d\n",
aipq_hist_data.pre_blue_pct);
count += sprintf(buf + count, "\n");
return count;
}
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;
vd_layer[0].property_changed = true;
}
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 ssize_t get_di_count_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", get_di_count);
}
static ssize_t get_di_count_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtoint(buf, 0, &get_di_count);
if (r < 0)
return -EINVAL;
return count;
}
static ssize_t put_di_count_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", put_di_count);
}
static ssize_t put_di_count_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtoint(buf, 0, &put_di_count);
if (r < 0)
return -EINVAL;
return count;
}
static ssize_t di_release_count_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", di_release_count);
}
static ssize_t di_release_count_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtoint(buf, 0, &di_release_count);
if (r < 0)
return -EINVAL;
return 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 =
LAYER1_CANVAS_BASE_INDEX + 5;
hist_test_vf.canvas1Addr =
LAYER1_CANVAS_BASE_INDEX + 5;
canvas_config
(LAYER1_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,
1080 | 1920);
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_switch_videolayer(0, false, false);
}
return strnlen(buf, count);
}
struct video_layer_s *get_layer_by_layer_id(u8 layer_id)
{
struct video_layer_s *layer = NULL;
if (layer_id == 0) {
layer = &vd_layer[0];
} else if (layer_id == 1) {
if (vd_layer[layer_id].vpp_index == VPP0)
layer = &vd_layer[1];
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
layer = &vd_layer_vpp[0];
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
layer = &vd_layer_vpp[1];
} else if (layer_id == 2) {
if (vd_layer[layer_id].vpp_index == VPP0)
layer = &vd_layer[2];
/* vpp1 case */
else if (vd_layer_vpp[0].layer_id == layer_id &&
vd_layer_vpp[0].vpp_index == VPP1)
layer = &vd_layer_vpp[0];
/* vpp2 case */
else if (vd_layer_vpp[1].layer_id == layer_id &&
vd_layer_vpp[1].vpp_index == VPP2)
layer = &vd_layer_vpp[1];
}
return layer;
}
int _videopip_set_disable(u32 index, u32 val)
{
struct video_layer_s *layer = NULL;
if (val > VIDEO_DISABLE_FORNEXT)
return -EINVAL;
layer = get_layer_by_layer_id(index);
if (!layer)
return -EINVAL;
layer->disable_video = val;
if (layer->disable_video ==
VIDEO_DISABLE_FORNEXT &&
layer->dispbuf &&
!is_local_vf(layer->dispbuf))
layer->disable_video = VIDEO_DISABLE_NONE;
if (layer->disable_video != VIDEO_DISABLE_NONE) {
pr_info("VID: VD%d off\n", index + 1);
safe_switch_videolayer
(layer->layer_id, false, true);
if (layer->disable_video ==
VIDEO_DISABLE_FORNEXT &&
layer->dispbuf &&
!is_local_vf(layer->dispbuf))
layer->property_changed = true;
/* FIXME */
if (layer->keep_frame_id == 2)
try_free_keep_videopip2(0);
else if (layer->keep_frame_id == 1)
try_free_keep_videopip(0);
else if (vd_layer[0].keep_frame_id == 0)
try_free_keep_video(0);
} else {
if (layer->dispbuf &&
!is_local_vf(layer->dispbuf)) {
safe_switch_videolayer
(layer->layer_id, true, true);
pr_info("VID: VD%d on\n", index + 1);
layer->property_changed = true;
}
}
return 0;
}
static ssize_t videopip_blackout_policy_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", blackout_pip);
}
static ssize_t videopip_blackout_policy_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(buf, 0, &blackout_pip);
if (r < 0)
return -EINVAL;
return count;
}
static ssize_t videopip2_blackout_policy_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", blackout_pip2);
}
static ssize_t videopip2_blackout_policy_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(buf, 0, &blackout_pip2);
if (r < 0)
return -EINVAL;
return count;
}
static ssize_t videopip_axis_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 videopip_axis_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 videopip2_axis_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
int x0, y0, x1, y1;
struct disp_info_s *layer = &glayer_info[2];
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 videopip2_axis_store(struct class *cla,
struct class_attribute *attr,
const char *buf,
size_t count)
{
struct disp_info_s *layer = &glayer_info[2];
mutex_lock(&video_module_mutex);
set_video_window(layer, buf);
mutex_unlock(&video_module_mutex);
return strnlen(buf, count);
}
static ssize_t videopip_crop_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 videopip_crop_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 videopip2_crop_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
u32 t, l, b, r;
struct disp_info_s *layer = &glayer_info[2];
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 videopip2_crop_store(struct class *cla,
struct class_attribute *attr,
const char *buf,
size_t count)
{
struct disp_info_s *layer = &glayer_info[2];
mutex_lock(&video_module_mutex);
set_video_crop(layer, buf);
mutex_unlock(&video_module_mutex);
return strnlen(buf, count);
}
static ssize_t videopip_disable_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", vd_layer[1].disable_video);
}
static ssize_t videopip_disable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int val;
if (debug_flag & DEBUG_FLAG_BASIC_INFO)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (_videopip_set_disable(VD2_PATH, val) < 0)
return -EINVAL;
return count;
}
static ssize_t videopip2_disable_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", vd_layer[2].disable_video);
}
static ssize_t videopip2_disable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int val;
if (debug_flag & DEBUG_FLAG_BASIC_INFO)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (_videopip_set_disable(VD3_PATH, val) < 0)
return -EINVAL;
return count;
}
static ssize_t videopip_screen_mode_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 videopip_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[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;
vd_layer[1].property_changed = true;
}
return count;
}
static ssize_t videopip2_screen_mode_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
struct disp_info_s *layer = &glayer_info[2];
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 videopip2_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[2];
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;
vd_layer[2].property_changed = true;
}
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;
u32 val;
r = kstrtouint(buf, 0, &val);
if (r < 0)
return -EINVAL;
pip_loop = val;
return count;
}
static ssize_t videopip2_loop_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", pip2_loop);
}
static ssize_t videopip2_loop_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
u32 val;
r = kstrtouint(buf, 0, &val);
if (r < 0)
return -EINVAL;
pip2_loop = val;
return count;
}
static ssize_t videopip_global_output_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n",
vd_layer[1].global_output);
}
static ssize_t videopip_global_output_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(buf, 0, &vd_layer[1].global_output);
if (r < 0)
return -EINVAL;
pr_info("%s(%d)\n", __func__, vd_layer[1].global_output);
return count;
}
static ssize_t videopip2_global_output_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n",
vd_layer[2].global_output);
}
static ssize_t videopip2_global_output_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtouint(buf, 0, &vd_layer[2].global_output);
if (r < 0)
return -EINVAL;
pr_info("%s(%d)\n", __func__, vd_layer[2].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;
vd_layer[1].property_changed = true;
}
return count;
}
static ssize_t videopip2_zorder_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
struct disp_info_s *layer = &glayer_info[2];
return sprintf(buf, "%d\n", layer->zorder);
}
static ssize_t videopip2_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[2];
ret = kstrtoint(buf, 0, &zorder);
if (ret < 0)
return -EINVAL;
if (zorder != layer->zorder) {
layer->zorder = zorder;
vd_layer[2].property_changed = true;
}
return count;
}
static ssize_t aisr_state_show(char *buf)
{
ssize_t len = 0;
struct vpp_frame_par_s *_cur_frame_par = NULL;
struct vppfilter_mode_s *vpp_filter = NULL;
struct aisr_setting_s *aisr_mif_setting = &vd_layer[0].aisr_mif_setting;
_cur_frame_par = &cur_dev->aisr_frame_parms;
if (!_cur_frame_par)
return len;
if (!aisr_mif_setting->aisr_enable)
return len;
vpp_filter = &_cur_frame_par->vpp_filter;
len += sprintf(buf + len,
"src_w:%u.src_h:%u.\n",
aisr_mif_setting->src_w, aisr_mif_setting->src_h);
len += sprintf(buf + len,
"in_ratio:%u.\n",
aisr_mif_setting->in_ratio);
len += sprintf(buf + len,
"phy_addr:%ld.\n",
aisr_mif_setting->phy_addr);
len += sprintf(buf + len,
"reshape_output_w:%d.\n",
_cur_frame_par->reshape_output_w);
len += sprintf(buf + len,
"reshape_output_h:%d.\n",
_cur_frame_par->reshape_output_h);
len += sprintf(buf + len,
"nnhf_input_w:%d.\n",
_cur_frame_par->nnhf_input_w);
len += sprintf(buf + len,
"nnhf_input_h:%d.\n",
_cur_frame_par->nnhf_input_h);
len += sprintf(buf + len,
"crop_top:%d.\n",
_cur_frame_par->crop_top);
len += sprintf(buf + len,
"crop_bottom:%d.\n",
_cur_frame_par->crop_bottom);
len += sprintf(buf + len,
"vscale_skip_count:%d.\n",
_cur_frame_par->vscale_skip_count);
len += sprintf(buf + len,
"hsc_rpt_p0_num0:%d.\n",
_cur_frame_par->hsc_rpt_p0_num0);
len += sprintf(buf + len,
"vsc_top_rpt_l0_num:%d.\n",
_cur_frame_par->vsc_top_rpt_l0_num);
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, "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 vdx_state_show(u32 index, char *buf)
{
ssize_t len = 0;
struct vppfilter_mode_s *vpp_filter = NULL;
struct vpp_frame_par_s *_cur_frame_par = NULL;
struct video_layer_s *_vd_layer = NULL;
switch (index) {
case 0:
_cur_frame_par = cur_frame_par;
_vd_layer = &vd_layer[0];
break;
case 1:
_cur_frame_par = curpip_frame_par;
_vd_layer = &vd_layer[1];
break;
case 2:
_cur_frame_par = curpip2_frame_par;
_vd_layer = &vd_layer[2];
break;
}
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",
_vd_layer->start_x_lines, _vd_layer->end_x_lines);
len += sprintf(buf + len,
"zoom_start_y_lines:%u.zoom_end_y_lines:%u.\n",
_vd_layer->start_y_lines, _vd_layer->end_x_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);
if (index == 0) {
#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);
if (index == 0)
len += aisr_state_show(buf + len);
return len;
}
static ssize_t video_state_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return vdx_state_show(VD1_PATH, buf);
}
static ssize_t videopip_state_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return vdx_state_show(VD2_PATH, buf);
}
static ssize_t videopip2_state_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return vdx_state_show(VD3_PATH, buf);
}
s32 set_video_path_select(const char *recv_name, u8 layer_id)
{
u32 new_path_id;
struct disp_info_s *layer_info;
struct video_layer_s *layer;
if (!recv_name ||
layer_id >= MAX_VD_LAYERS)
return -1;
layer_info = &glayer_info[layer_id];
layer = get_layer_by_layer_id(layer_id);
new_path_id = layer_info->display_path_id;
if (!strcmp(recv_name, "default"))
new_path_id = VFM_PATH_DEF;
else if (!strcmp(recv_name, RECEIVER_NAME))
new_path_id = VFM_PATH_AMVIDEO;
else if (!strcmp(recv_name, RECEIVERPIP_NAME))
new_path_id = VFM_PATH_PIP;
else if (!strcmp(recv_name, RECEIVERPIP2_NAME))
new_path_id = VFM_PATH_PIP2;
else if (!strcmp(recv_name, "video_render.0"))
new_path_id = VFM_PATH_VIDEO_RENDER0;
else if (!strcmp(recv_name, "video_render.1"))
new_path_id = VFM_PATH_VIDEO_RENDER1;
else if (!strcmp(recv_name, "video_render.2"))
new_path_id = VFM_PATH_VIDEO_RENDER2;
else if (!strcmp(recv_name, "video_render.5"))
new_path_id = VFM_PATH_VIDEO_RENDER5;
else if (!strcmp(recv_name, "video_render.6"))
new_path_id = VFM_PATH_VIDEO_RENDER6;
else if (!strcmp(recv_name, "auto"))
new_path_id = VFM_PATH_AUTO;
else if (!strcmp(recv_name, "invalid"))
new_path_id = VFM_PATH_INVALID;
if (layer_info->display_path_id != new_path_id && layer) {
pr_info("VID: store VD%d path_id changed %d->%d\n",
layer_id, layer_info->display_path_id, new_path_id);
layer_info->display_path_id = new_path_id;
layer->property_changed = true;
if (new_path_id == VFM_PATH_AUTO)
layer_info->sideband_type = -1;
}
return 0;
}
EXPORT_SYMBOL(set_video_path_select);
s32 set_sideband_type(s32 type, u8 layer_id)
{
struct disp_info_s *layer_info;
if (layer_id >= MAX_VD_LAYERS)
return -1;
layer_info = &glayer_info[layer_id];
pr_info("VID: sideband_type %d changed to %d\n",
layer_info->sideband_type, type);
layer_info->sideband_type = type;
return 0;
}
EXPORT_SYMBOL(set_sideband_type);
static ssize_t path_select_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "vd1: %d vd2: %d, vd3: %d\n",
glayer_info[0].display_path_id,
glayer_info[1].display_path_id,
glayer_info[2].display_path_id);
}
static ssize_t path_select_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[3];
if (likely(parse_para(buf, 3, parsed) == 3)) {
if (glayer_info[0].display_path_id != parsed[0]) {
pr_info("VID: store VD1 path_id changed %d->%d\n",
glayer_info[0].display_path_id, parsed[0]);
glayer_info[0].display_path_id = parsed[0];
vd_layer[0].property_changed = true;
}
if (glayer_info[1].display_path_id != parsed[1]) {
pr_info("VID: store VD2 path_id changed %d->%d\n",
glayer_info[1].display_path_id, parsed[1]);
glayer_info[1].display_path_id = parsed[1];
vd_layer[1].property_changed = true;
}
if (glayer_info[2].display_path_id != parsed[2]) {
pr_info("VID: store VD3 path_id changed %d->%d\n",
glayer_info[2].display_path_id, parsed[2]);
glayer_info[2].display_path_id = parsed[2];
vd_layer[2].property_changed = true;
}
} else {
pr_err("need 3 input params\n");
}
return strnlen(buf, count);
}
static ssize_t vpp_crc_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 64, "vpp_crc_en: %d vpp_crc_result: %x\n\n",
vpp_crc_en,
vpp_crc_result);
}
static ssize_t vpp_crc_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtouint(buf, 0, &vpp_crc_en);
if (ret < 0)
return -EINVAL;
return count;
}
static ssize_t vpp_crc_viu2_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
int vpp_crc_viu2_result = 0;
if (amvideo_meson_dev.cpu_type >= MESON_CPU_MAJOR_ID_SC2_)
vpp_crc_viu2_result = vpp_crc_viu2_check(vpp_crc_viu2_en);
return snprintf(buf, 64, "crc_viu2_en: %d crc_vui2_result: %x\n\n",
vpp_crc_viu2_en,
vpp_crc_viu2_result);
}
static ssize_t vpp_crc_viu2_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtouint(buf, 0, &vpp_crc_viu2_en);
if (ret < 0)
return -EINVAL;
if (amvideo_meson_dev.cpu_type >= MESON_CPU_MAJOR_ID_SC2_)
enable_vpp_crc_viu2(vpp_crc_viu2_en);
return count;
}
static ssize_t film_grain_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "fgrain_enable vd1: %d vd2: %d vd3: %d\n",
glayer_info[0].fgrain_enable,
glayer_info[1].fgrain_enable,
glayer_info[2].fgrain_enable);
}
static ssize_t film_grain_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[3];
if (likely(parse_para(buf, 3, parsed) == 3)) {
glayer_info[0].fgrain_enable = parsed[0];
glayer_info[1].fgrain_enable = parsed[1];
glayer_info[2].fgrain_enable = parsed[2];
} else {
pr_err("need 3 input params\n");
}
return strnlen(buf, count);
}
static ssize_t pip_alpha_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
int param_num;
int parsed[66];
int layer_id, win_num, win_en = 0;
struct pip_alpha_scpxn_s alpha_win;
if (likely(parse_para(buf, 2, parsed) >= 2)) {
layer_id = parsed[0];
win_num = parsed[1];
param_num = win_num * 4 + 2;
if (likely(parse_para(buf, param_num, parsed) == param_num)) {
for (i = 0; i < win_num; i++) {
alpha_win.scpxn_bgn_h[i] = parsed[2 + i * 4];
alpha_win.scpxn_end_h[i] = parsed[3 + i * 4];
alpha_win.scpxn_bgn_v[i] = parsed[4 + i * 4];
alpha_win.scpxn_end_v[i] = parsed[5 + i * 4];
win_en |= 1 << i;
}
pr_info("layer_id=%d, win_num=%d, win_en=%d\n",
layer_id, win_num, win_en);
set_alpha(&vd_layer[layer_id], win_en, &alpha_win);
}
}
return strnlen(buf, count);
}
/*
* default setting scenes is 23
*/
static ssize_t pq_default_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
ssize_t count;
int i = 0;
char end[4] = "\n";
char temp[20] = "default scene pq:";
count = sprintf(buf, "%s", temp);
while (i < SCENES_VALUE)
count += sprintf(buf + count, " %d",
vpp_scenes[AI_SCENES_MAX - 1].pq_values[i++]);
count += sprintf(buf + count, " %s", end);
return count;
}
static ssize_t pq_default_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
int parsed[SCENES_VALUE];
if (likely(parse_para(buf, SCENES_VALUE, parsed) == SCENES_VALUE)) {
vpp_scenes[AI_SCENES_MAX - 1].pq_scenes = DEFAUT_SETTING;
while (i < SCENES_VALUE) {
vpp_scenes[AI_SCENES_MAX - 1].pq_values[i] = parsed[i];
i++;
}
}
i = 0;
pr_info("the default scene pq param: ");
while (i < SCENES_VALUE)
pr_info("%d ", vpp_scenes[AI_SCENES_MAX - 1].pq_values[i++]);
pr_info("\n");
return strnlen(buf, count);
}
static ssize_t pq_data_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[4] = {0, 0, 0, 0};
ssize_t buflen;
int ret;
buflen = strlen(buf);
if (buflen <= 0)
return 0;
ret = parse_para(buf, 4, parsed);
if (ret == 4 && parsed[0]) {
if (parsed[1] < AI_SCENES_MAX && parsed[1] >= 0 &&
parsed[2] < SCENES_VALUE && parsed[2] >= 0 &&
parsed[3] >= 0) {
vpp_scenes[parsed[1]].pq_scenes =
(enum ai_scenes)parsed[1];
vpp_scenes[parsed[1]].pq_values[parsed[2]] = parsed[3];
} else {
pr_info("the 2nd param: 0~23,the 3rd param: 0~9,the 4th param: >=0\n");
}
} else if (ret == 3 && parsed[0] == 0) {
if (parsed[1] < AI_SCENES_MAX && parsed[1] >= 0 &&
parsed[2] < SCENES_VALUE && parsed[2] >= 0)
pr_info("pq value: %d\n",
vpp_scenes[parsed[1]].pq_values[parsed[2]]);
else
pr_info("the 2nd param: 0~23,the 3rd param: 0~9\n");
} else {
if (parsed[0] == 0)
pr_info("1st param 0 is to read pq value,need set 3 param\n");
else
pr_info("1st param 1 is to set pq value,need set 4 param\n");
}
return strnlen(buf, count);
}
static ssize_t aipq_dbg_data_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
ssize_t len = 0;
char *stemp = NULL;
int i, j;
int stemp_len = AI_SCENES_CUR_USE_MAX * SCENES_CUR_USE_VALUE * 3;
stemp = kmalloc(stemp_len, GFP_KERNEL);
if (!stemp)
return 0;
memset(stemp, 0, stemp_len);
for (i = 0; i < AI_SCENES_CUR_USE_MAX; i++) {
for (j = 0; j < SCENES_CUR_USE_VALUE; j++) {
int_convert_str(vpp_pq_data[i][j],
stemp, 10);
}
}
len = sprintf(buf, "for_tool:%s\n", stemp);
kfree(stemp);
return len;
}
static ssize_t aipq_dbg_data_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i, j;
char *buf_orig, *parm[8] = {NULL};
int aipq_data[AI_SCENES_CUR_USE_MAX * SCENES_CUR_USE_VALUE] = {0};
if (!buf)
return count;
buf_orig = kstrdup(buf, GFP_KERNEL);
if (!buf_orig)
return -ENOMEM;
parse_param_to_char(buf_orig, (char **)&parm);
if (!strncmp(parm[0], "w", 1)) {
if (strlen(parm[1]) !=
AI_SCENES_CUR_USE_MAX * SCENES_CUR_USE_VALUE * 3) {
goto free_buf;
}
str_sapr_conv(parm[1], 3,
aipq_data,
AI_SCENES_CUR_USE_MAX * SCENES_CUR_USE_VALUE);
for (i = 0; i < AI_SCENES_CUR_USE_MAX; i++)
for (j = 0; j < SCENES_CUR_USE_VALUE; j++)
vpp_pq_data[i][j] =
aipq_data[i * SCENES_CUR_USE_VALUE + j];
} else if (!strncmp(parm[0], "r", 1)) {
int i, j;
for (i = 0; i < AI_SCENES_MAX; i++) {
for (j = 0; j < SCENES_VALUE; j++)
pr_info("%d ", vpp_pq_data[i][j]);
}
} else {
pr_info("aipq_dbg cmd invalid!!!\n");
}
kfree(buf_orig);
return count;
free_buf:
kfree(buf_orig);
return -EINVAL;
}
static ssize_t hscaler_8tap_enable_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 64, "hscaler_8tap_en: %d\n\n",
hscaler_8tap_enable[0]);
}
static ssize_t hscaler_8tap_enable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int hscaler_8tap_en;
ret = kstrtoint(buf, 0, &hscaler_8tap_en);
if (ret < 0)
return -EINVAL;
if (amvideo_meson_dev.has_hscaler_8tap[0] &&
hscaler_8tap_en != hscaler_8tap_enable[0]) {
hscaler_8tap_enable[0] = hscaler_8tap_en;
}
return count;
}
static ssize_t pip_hscaler_8tap_enable_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 64, "pip hscaler_8tap_en: %d\n\n",
hscaler_8tap_enable[1]);
}
static ssize_t pip_hscaler_8tap_enable_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int hscaler_8tap_en;
ret = kstrtoint(buf, 0, &hscaler_8tap_en);
if (ret < 0)
return -EINVAL;
if (amvideo_meson_dev.has_hscaler_8tap[1] &&
hscaler_8tap_en != hscaler_8tap_enable[1]) {
hscaler_8tap_enable[1] = hscaler_8tap_en;
}
return count;
}
static ssize_t pip2_hscaler_8tap_enable_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 64, "pip2_hscaler_8tap_en: %d\n\n",
hscaler_8tap_enable[2]);
}
static ssize_t pip2_hscaler_8tap_enable_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int hscaler_8tap_en;
ret = kstrtoint(buf, 0, &hscaler_8tap_en);
if (ret < 0)
return -EINVAL;
if (amvideo_meson_dev.has_hscaler_8tap[2] &&
hscaler_8tap_en != hscaler_8tap_enable[2]) {
hscaler_8tap_enable[2] = hscaler_8tap_en;
}
return count;
}
static ssize_t pre_hscaler_ntap_enable_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
int i;
for (i = 0; i < MAX_VD_LAYER; i++) {
if (pre_hscaler_ntap_set[i] == 0xff)
pr_info("pre_hscaler_ntap_en[%d](0xff):%d\n",
i,
pre_hscaler_ntap_enable[i]);
else
pr_info("pre_hscaler_ntap_en[%d]: %d\n",
i,
pre_hscaler_ntap_set[i]);
}
return 0;
}
static ssize_t pre_hscaler_ntap_enable_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[2];
int layer_id = 0, pre_hscaler_ntap_en = 0;
if (likely(parse_para(buf, 2, parsed) == 2)) {
if (parsed[0] < MAX_VD_LAYER)
layer_id = parsed[0];
pre_hscaler_ntap_en = parsed[1];
if (pre_hscaler_ntap_en != pre_hscaler_ntap_set[layer_id])
pre_hscaler_ntap_set[layer_id] = pre_hscaler_ntap_en;
}
return strnlen(buf, count);
}
static ssize_t pre_hscaler_ntap_set_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 256, "pre_hscaler_ntap: vd1:%d, vd2:%d, vd3:%d\n",
pre_hscaler_ntap[0],
pre_hscaler_ntap[1],
pre_hscaler_ntap[2]);
}
static ssize_t cur_ai_scenes_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
ssize_t count;
int i = 0;
if (!vd_layer[0].dispbuf)
return 0;
if (nn_scenes_value[0].maxprob == 0)
return 0;
if (vd_layer[0].disable_video == 1 ||
vd_layer[0].global_output == 0)
return 0;
count = 0;
while (i < AI_PQ_TOP - 1) {
count += sprintf(buf + count, "%d:",
nn_scenes_value[i].maxclass);
count += sprintf(buf + count, "%d;",
nn_scenes_value[i].maxprob);
i++;
}
count += sprintf(buf + count, "\n");
return count;
}
static ssize_t pre_hscaler_ntap_set_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[2];
int layer_id = 0;
if (likely(parse_para(buf, 2, parsed) == 2)) {
if (parsed[0] < MAX_VD_LAYER)
layer_id = parsed[0];
pre_hscaler_ntap[layer_id] = parsed[1];
}
return strnlen(buf, count);
}
static ssize_t pre_vscaler_ntap_enable_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
int i;
for (i = 0; i < MAX_VD_LAYER; i++) {
if (pre_vscaler_ntap_set[i] == 0xff)
pr_info("pre_vscaler_ntap_en[%d](0xff):%d\n",
i,
pre_vscaler_ntap_enable[i]);
else
pr_info("pre_vscaler_ntap_en[%d]: %d\n",
i,
pre_vscaler_ntap_set[i]);
}
return 0;
}
static ssize_t pre_vscaler_ntap_enable_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[2];
int layer_id = 0, pre_vscaler_ntap_en = 0;
if (likely(parse_para(buf, 2, parsed) == 2)) {
if (parsed[0] < MAX_VD_LAYER)
layer_id = parsed[0];
pre_vscaler_ntap_en = parsed[1];
if (pre_vscaler_ntap_en != pre_vscaler_ntap_set[layer_id])
pre_vscaler_ntap_set[layer_id] = pre_vscaler_ntap_en;
}
return strnlen(buf, count);
}
static ssize_t pre_vscaler_ntap_set_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 256, "pre_vscaler_ntap: vd1:%d, vd2:%d, vd3:%d\n",
pre_vscaler_ntap[0],
pre_vscaler_ntap[1],
pre_vscaler_ntap[2]);
}
static ssize_t pre_vscaler_ntap_set_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[2];
int layer_id = 0;
if (likely(parse_para(buf, 2, parsed) == 2)) {
if (parsed[0] < MAX_VD_LAYER)
layer_id = parsed[0];
pre_vscaler_ntap[layer_id] = parsed[1];
}
return strnlen(buf, count);
}
static ssize_t force_switch_vf_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", force_switch_vf_mode);
}
static ssize_t force_switch_vf_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int force;
ret = kstrtoint(buf, 0, &force);
if (ret < 0)
return -EINVAL;
if (force >= 0 && force <= 2 &&
force_switch_vf_mode != force) {
force_switch_vf_mode = force;
vd_layer[0].property_changed = true;
vd_layer[1].property_changed = true;
vd_layer[2].property_changed = true;
vd_layer_vpp[0].property_changed = true;
vd_layer_vpp[1].property_changed = true;
}
return count;
}
static ssize_t force_property_change_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int force;
ret = kstrtoint(buf, 0, &force);
if (ret < 0)
return -EINVAL;
if (force) {
vd_layer[0].property_changed = true;
vd_layer[1].property_changed = true;
vd_layer[2].property_changed = true;
vd_layer_vpp[0].property_changed = true;
vd_layer_vpp[1].property_changed = true;
}
return count;
}
static ssize_t probe_en_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int probe_en;
ret = kstrtoint(buf, 0, &probe_en);
if (ret < 0)
return -EINVAL;
vpp_probe_en_set(probe_en);
return count;
}
static ssize_t mirror_axis_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "%d (1: H_MIRROR 2: V_MIRROR)\n", mirror);
}
static ssize_t mirror_axis_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
pr_info("mirror: %d->%d (1: H_MIRROR 2: V_MIRROR)\n", mirror, res);
mirror = res;
_set_video_mirror(&glayer_info[0], mirror);
_set_video_mirror(&glayer_info[1], mirror);
_set_video_mirror(&glayer_info[2], mirror);
return count;
}
static ssize_t pps_coefs_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[3];
int layer_id = 0, bit9_mode = 0, coef_type = 0;
if (likely(parse_para(buf, 3, parsed) == 3)) {
layer_id = parsed[0];
bit9_mode = parsed[1];
coef_type = parsed[2];
}
dump_pps_coefs_info(layer_id, bit9_mode, coef_type);
return strnlen(buf, count);
}
static ssize_t load_pps_coefs_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
load_pps_coef = res;
return count;
}
static ssize_t reg_dump_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
if (res) {
dump_mif_reg();
dump_afbc_reg();
dump_pps_reg();
dump_vpp_blend_reg();
dump_vpp_path_size_reg();
dump_vpp_misc_reg();
dump_zorder_reg();
dump_fgrain_reg();
if (cur_dev->aisr_support)
dump_aisr_reg();
}
return count;
}
static ssize_t primary_src_fmt_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
int ret = 0;
enum vframe_signal_fmt_e fmt;
fmt = (enum vframe_signal_fmt_e)atomic_read(&cur_primary_src_fmt);
if (fmt != VFRAME_SIGNAL_FMT_INVALID)
ret += sprintf(buf + ret, "src_fmt = %s\n",
src_fmt_str[fmt]);
else
ret += sprintf(buf + ret, "src_fmt = invalid\n");
return ret;
}
static ssize_t status_changed_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
u32 status = 0;
status = atomic_read(&status_changed);
return sprintf(buf, "0x%x\n", status);
}
static ssize_t vd_attach_vpp_show
(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 256, "vpp_index: vd1:%d, vd2:%d, vd3:%d\n",
vd_layer[0].vpp_index,
vd_layer[1].vpp_index,
vd_layer[2].vpp_index);
}
static ssize_t vd_attach_vpp_store
(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[2];
int layer_id = 0;
/* parsed[0]: layer_id */
/* parsed[1]: vpp index */
if (likely(parse_para(buf, 2, parsed) == 2)) {
if (parsed[0] < MAX_VD_LAYER)
layer_id = parsed[0];
vd_layer[layer_id].vpp_index = parsed[1];
if (layer_id >= 1) {
if (parsed[1] == VPP1) {
vd_layer_vpp[0].vpp_index = VPP1;
vd_layer_vpp[0].layer_id = layer_id;
} else if (parsed[1] == VPP2) {
vd_layer_vpp[1].vpp_index = VPP2;
vd_layer_vpp[1].layer_id = layer_id;
}
}
}
return strnlen(buf, count);
}
static ssize_t blend_conflict_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "blend_conflict_cnt: %d\n", blend_conflict_cnt);
}
static ssize_t force_disable_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "force_disable: %d %d %d\n",
vd_layer[0].force_disable ? 1 : 0,
vd_layer[1].force_disable ? 1 : 0,
vd_layer[2].force_disable ? 1 : 0);
}
static ssize_t vd1_vd2_mux_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "vd1_vd2_mux:%d(for t5d revb)\n", vd1_vd2_mux);
}
static ssize_t vd1_vd2_mux_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
vd1_vd2_mux = res;
vd_layer[0].vd1_vd2_mux = res;
if (vd1_vd2_mux)
di_used_vd1_afbc(true);
else
di_used_vd1_afbc(false);
return count;
}
static ssize_t aisr_en_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "aisr en:%d\n", aisr_en);
}
static ssize_t aisr_en_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
aisr_en = res;
aisr_sr1_nn_enable(aisr_en);
return count;
}
static ssize_t reshape_output_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
aisr_reshape_output(res);
return count;
}
static ssize_t pps_auto_calc_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "aisr pps_auto_calc:%d\n", cur_dev->pps_auto_calc);
}
static ssize_t ai_pq_disable_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "for_tool:%d\n", ai_pq_disable);
}
static ssize_t ai_pq_disable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
ai_pq_disable = tmp;
return count;
}
static ssize_t ai_pq_debug_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "for_tool:%d\n", ai_pq_debug);
}
static ssize_t ai_pq_debug_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
ai_pq_debug = tmp;
return count;
}
static ssize_t ai_pq_value_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "for_tool:%d\n", ai_pq_value);
}
static ssize_t ai_pq_value_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
ai_pq_value = tmp;
return count;
}
static ssize_t ai_pq_policy_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "for_tool:%d\n", ai_pq_policy);
}
static ssize_t ai_pq_policy_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
ai_pq_policy = tmp;
return count;
}
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
static ssize_t det_stb_cnt_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "det_stb_cnt: %d\n", det_stb_cnt);
}
static ssize_t det_stb_cnt_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
det_stb_cnt = tmp;
return count;
}
static ssize_t det_unstb_cnt_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "det_unstb_cnt: %d\n", det_unstb_cnt);
}
static ssize_t det_unstb_cnt_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
det_unstb_cnt = tmp;
return count;
}
static ssize_t tolrnc_cnt_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "tolrnc_cnt: %d\n", tolrnc_cnt);
}
static ssize_t tolrnc_cnt_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
tolrnc_cnt = tmp;
return count;
}
static ssize_t timer_filter_en_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "timer_filter_en: %d\n", timer_filter_en);
}
static ssize_t timer_filter_en_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
timer_filter_en = tmp;
return count;
}
static ssize_t aipq_set_policy_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "aipq_set_policy: %d\n", aipq_set_policy);
}
static ssize_t aipq_set_policy_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
aipq_set_policy = tmp;
return count;
}
static ssize_t color_th_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "color_th: %d\n", color_th);
}
static ssize_t color_th_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
long tmp;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
pr_info("ERROR converting %s to long int!\n", buf);
return ret;
}
color_th = tmp;
return count;
}
static ssize_t aisr_demo_en_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "aisr_demo_en: %d\n", cur_dev->aisr_demo_en);
}
static ssize_t aisr_demo_en_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int res;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
cur_dev->aisr_demo_en = res;
aisr_demo_enable();
return count;
}
static ssize_t aisr_demo_axis_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "aisr_demo_axis: %d,%d,%d,%d\n",
cur_dev->aisr_demo_xstart,
cur_dev->aisr_demo_ystart,
cur_dev->aisr_demo_xend,
cur_dev->aisr_demo_yend);
}
static ssize_t aisr_demo_axis_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[4];
if (likely(parse_para(buf, 4, parsed) == 4)) {
cur_dev->aisr_demo_xstart = parsed[0];
cur_dev->aisr_demo_ystart = parsed[1];
cur_dev->aisr_demo_xend = parsed[2];
cur_dev->aisr_demo_yend = parsed[3];
aisr_demo_axis_set();
}
return count;
}
static ssize_t power_ctrl_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "power_ctrl: %d\n", cur_dev->power_ctrl);
}
static ssize_t power_ctrl_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int res;
ret = kstrtoint(buf, 0, &res);
if (ret) {
pr_err("kstrtoint err\n");
return -EINVAL;
}
if (res) {
pr_info("enable power_ctrl, disable vd scaler/SR clk\n");
cur_dev->power_ctrl = res;
vpu_module_clk_disable(VPP0, VD1_SCALER, 1);
vpu_module_clk_disable(VPP0, VD2_SCALER, 1);
vpu_module_clk_disable(VPP0, SR0, 1);
vpu_module_clk_disable(VPP0, SR1, 1);
vpu_module_clk_disable(VPP0, VD1_HDR_CORE, 1);
vpu_module_clk_disable(VPP0, VD2_HDR_CORE, 1);
vpu_module_clk_disable(VPP0, OSD1_HDR_CORE, 1);
vpu_module_clk_disable(VPP0, OSD2_HDR_CORE, 1);
vpu_module_clk_disable(VPP0, DV_TVCORE, 1);
} else {
pr_info("disable power_ctrl, enable vd scaler/SR clk\n");
vpu_module_clk_enable(VPP0, VD1_SCALER, 1);
vpu_module_clk_enable(VPP0, VD2_SCALER, 1);
vpu_module_clk_enable(VPP0, SR0, 1);
vpu_module_clk_enable(VPP0, SR1, 1);
vpu_module_clk_enable(VPP0, VD1_HDR_CORE, 1);
vpu_module_clk_enable(VPP0, VD2_HDR_CORE, 1);
vpu_module_clk_enable(VPP0, OSD1_HDR_CORE, 1);
vpu_module_clk_enable(VPP0, OSD2_HDR_CORE, 1);
vpu_module_clk_enable(VPP0, DV_TVCORE, 1);
cur_dev->power_ctrl = res;
}
return count;
}
static ssize_t frc_delay_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
u32 frc_delay = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_FRC
frc_delay += frc_get_video_latency();
#endif
return sprintf(buf, "%d\n", frc_delay);
}
#endif
static ssize_t vpu_module_urgent_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
get_vpu_urgent_info();
return 0;
//return snprintf(buf, 80, "above vpu_module_urgent stat info\n");
}
static const char vpu_module_urgent_help[] = "Usage:\n"
" echo module_id low_level(0-7) high_level(0-7)> /sys/class/video/urgent_set\n"
" FRC0_R: 0\n"
" FRC0_W: 1\n"
" FRC1_R: 2\n"
" FRC1_W: 3\n"
" FRC2_R: 4\n"
" VPU0_R: 5\n"
" VPU0_W: 6\n"
" VPU1_R: 7\n"
" VPU1_W: 8\n"
" VPU2_R: 9\n\n";
static ssize_t vpu_module_urgent_set(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[3];
int ret = -1;
if (likely(parse_para(buf, 3, parsed) == 3))
ret = set_vpu_super_urgent(parsed[0], parsed[1], parsed[2]);
if (ret < 0)
pr_info("%s", vpu_module_urgent_help);
return count;
}
static struct class_attribute amvideo_class_attrs[] = {
__ATTR(axis,
0664,
video_axis_show,
video_axis_store),
__ATTR(crop,
0644,
video_crop_show,
video_crop_store),
__ATTR(sr,
0644,
video_sr_show,
video_sr_store),
__ATTR(global_offset,
0644,
video_global_offset_show,
video_global_offset_store),
__ATTR(screen_mode,
0664,
video_screen_mode_show,
video_screen_mode_store),
__ATTR(blackout_policy,
0664,
video_blackout_policy_show,
video_blackout_policy_store),
__ATTR(blackout_pip_policy,
0664,
videopip_blackout_policy_show,
videopip_blackout_policy_store),
__ATTR(blackout_pip2_policy,
0664,
videopip2_blackout_policy_show,
videopip2_blackout_policy_store),
__ATTR(video_seek_flag,
0664,
video_seek_flag_show,
video_seek_flag_store),
__ATTR(disable_video,
0664,
video_disable_show,
video_disable_store),
__ATTR(video_global_output,
0664,
video_global_output_show,
video_global_output_store),
__ATTR(hold_video,
0664,
video_hold_show,
video_hold_store),
__ATTR(zoom,
0664,
video_zoom_show,
video_zoom_store),
__ATTR(brightness,
0644,
video_brightness_show,
video_brightness_store),
__ATTR(contrast,
0644,
video_contrast_show,
video_contrast_store),
__ATTR(vpp_brightness,
0644,
vpp_brightness_show,
vpp_brightness_store),
__ATTR(vpp_contrast,
0644,
vpp_contrast_show,
vpp_contrast_store),
__ATTR(saturation,
0644,
video_saturation_show,
video_saturation_store),
__ATTR(vpp_saturation_hue,
0644,
vpp_saturation_hue_show,
vpp_saturation_hue_store),
__ATTR(video_background,
0644,
video_background_show,
video_background_store),
__ATTR(test_screen,
0644,
video_test_screen_show,
video_test_screen_store),
__ATTR(rgb_screen,
0644,
video_rgb_screen_show,
video_rgb_screen_store),
__ATTR(file_name,
0644,
video_filename_show,
video_filename_store),
__ATTR(debugflags,
0644,
video_debugflags_show,
video_debugflags_store),
__ATTR(trickmode_duration,
0644,
trickmode_duration_show,
trickmode_duration_store),
__ATTR(nonlinear_factor,
0644,
video_nonlinear_factor_show,
video_nonlinear_factor_store),
__ATTR(nonlinear_t_factor,
0644,
video_nonlinear_t_factor_show,
video_nonlinear_t_factor_store),
__ATTR(freerun_mode,
0644,
video_freerun_mode_show,
video_freerun_mode_store),
__ATTR(video_speed_check_h_w,
0644,
video_speed_check_show,
video_speed_check_store),
__ATTR(threedim_mode,
0644,
threedim_mode_show,
threedim_mode_store),
__ATTR(vsync_pts_inc_upint,
0644,
video_vsync_pts_inc_upint_show,
video_vsync_pts_inc_upint_store),
__ATTR(vsync_slow_factor,
0644,
video_vsync_slow_factor_show,
video_vsync_slow_factor_store),
__ATTR(angle,
0644,
video_angle_show,
video_angle_store),
__ATTR(stereo_scaler,
0644, NULL,
video_3d_scale_store),
__ATTR(show_first_frame_nosync,
0644,
show_first_frame_nosync_show,
show_first_frame_nosync_store),
__ATTR(show_first_picture,
0664, NULL,
show_first_picture_store),
__ATTR(slowsync_repeat_enable,
0644,
slowsync_repeat_enable_show,
slowsync_repeat_enable_store),
__ATTR(free_keep_buffer,
0664, NULL,
video_free_keep_buffer_store),
__ATTR(hdmin_delay_start,
0664,
hdmin_delay_start_show,
hdmin_delay_start_store),
__ATTR(hdmin_delay_duration,
0664,
hdmin_delay_duration_show,
hdmin_delay_duration_store),
__ATTR(hdmin_delay_min_ms,
0664,
hdmin_delay_min_ms_show,
hdmin_delay_min_ms_store),
__ATTR(hdmin_delay_max_ms,
0664,
hdmin_delay_max_ms_show,
hdmin_delay_max_ms_store),
__ATTR(vframe_walk_delay,
0664,
vframe_walk_delay_show, NULL),
__ATTR(last_required_total_delay,
0664,
last_required_total_delay_show, NULL),
__ATTR(free_cma_buffer,
0664, NULL,
free_cma_buffer_store),
#ifdef CONFIG_AM_VOUT
__ATTR_RO(device_resolution),
#endif
#ifdef PTS_TRACE_DEBUG
__ATTR_RO(pts_trace),
#endif
__ATTR(video_inuse,
0664,
video_inuse_show,
video_inuse_store),
__ATTR(video_zorder,
0664,
video_zorder_show,
video_zorder_store),
__ATTR(black_threshold,
0664,
black_threshold_show,
black_threshold_store),
__ATTR(get_di_count,
0664,
get_di_count_show,
get_di_count_store),
__ATTR(put_di_count,
0664,
put_di_count_show,
put_di_count_store),
__ATTR(di_release_count,
0664,
di_release_count_show,
di_release_count_store),
__ATTR(hist_test,
0664,
hist_test_show,
hist_test_store),
__ATTR_RO(frame_addr),
__ATTR_RO(frame_canvas_width),
__ATTR_RO(frame_canvas_height),
__ATTR_RO(frame_width),
__ATTR_RO(frame_height),
__ATTR_RO(frame_format),
__ATTR_RO(frame_aspect_ratio),
__ATTR_RO(frame_rate),
__ATTR_RO(vframe_states),
__ATTR_RO(video_state),
__ATTR_RO(fps_info),
__ATTR_RO(vframe_ready_cnt),
__ATTR_RO(video_layer1_state),
__ATTR_RO(pic_mode_info),
__ATTR_RO(src_fmt),
__ATTR_RO(cur_aipq_sp),
__ATTR_RO(process_fmt),
__ATTR(axis_pip,
0664,
videopip_axis_show,
videopip_axis_store),
__ATTR(crop_pip,
0664,
videopip_crop_show,
videopip_crop_store),
__ATTR(disable_videopip,
0664,
videopip_disable_show,
videopip_disable_store),
__ATTR(screen_mode_pip,
0664,
videopip_screen_mode_show,
videopip_screen_mode_store),
__ATTR(videopip_loop,
0664,
videopip_loop_show,
videopip_loop_store),
__ATTR(pip_global_output,
0664,
videopip_global_output_show,
videopip_global_output_store),
__ATTR(videopip_zorder,
0664,
videopip_zorder_show,
videopip_zorder_store),
__ATTR_RO(videopip_state),
__ATTR(axis_pip2,
0664,
videopip2_axis_show,
videopip2_axis_store),
__ATTR(crop_pip2,
0664,
videopip2_crop_show,
videopip2_crop_store),
__ATTR(disable_videopip2,
0664,
videopip2_disable_show,
videopip2_disable_store),
__ATTR(screen_mode_pip2,
0664,
videopip2_screen_mode_show,
videopip2_screen_mode_store),
__ATTR(videopip2_loop,
0664,
videopip2_loop_show,
videopip2_loop_store),
__ATTR(pip2_global_output,
0664,
videopip2_global_output_show,
videopip2_global_output_store),
__ATTR(videopip2_zorder,
0664,
videopip2_zorder_show,
videopip2_zorder_store),
__ATTR_RO(videopip2_state),
__ATTR(path_select,
0664,
path_select_show,
path_select_store),
__ATTR(vpp_crc,
0664,
vpp_crc_show,
vpp_crc_store),
__ATTR(vpp_crc_viu2,
0664,
vpp_crc_viu2_show,
vpp_crc_viu2_store),
__ATTR(pip_alpha,
0220,
NULL,
pip_alpha_store),
__ATTR(film_grain,
0664,
film_grain_show,
film_grain_store),
__ATTR(pq_default,
0664,
pq_default_show,
pq_default_store),
__ATTR(hscaler_8tap_en,
0664,
hscaler_8tap_enable_show,
hscaler_8tap_enable_store),
__ATTR(pip_hscaler_8tap_en,
0664,
pip_hscaler_8tap_enable_show,
pip_hscaler_8tap_enable_store),
__ATTR(pip2_hscaler_8tap_en,
0664,
pip2_hscaler_8tap_enable_show,
pip2_hscaler_8tap_enable_store),
__ATTR(pre_hscaler_ntap_en,
0664,
pre_hscaler_ntap_enable_show,
pre_hscaler_ntap_enable_store),
__ATTR(pre_hscaler_ntap,
0664,
pre_hscaler_ntap_set_show,
pre_hscaler_ntap_set_store),
__ATTR(pre_vscaler_ntap_en,
0664,
pre_vscaler_ntap_enable_show,
pre_vscaler_ntap_enable_store),
__ATTR_WO(pq_data),
__ATTR_RO(cur_ai_scenes),
__ATTR(pre_vscaler_ntap,
0664,
pre_vscaler_ntap_set_show,
pre_vscaler_ntap_set_store),
__ATTR(force_switch_vf,
0644,
force_switch_vf_show,
force_switch_vf_store),
__ATTR(force_property_change,
0644, NULL,
force_property_change_store),
__ATTR(probe_en,
0644,
NULL,
probe_en_store),
__ATTR(mirror,
0664,
mirror_axis_show,
mirror_axis_store),
__ATTR(pps_coefs,
0664,
NULL,
pps_coefs_store),
__ATTR(load_pps_coefs,
0664,
NULL,
load_pps_coefs_store),
__ATTR(reg_dump,
0220,
NULL,
reg_dump_store),
__ATTR(vd_attch_vpp,
0664,
vd_attach_vpp_show,
vd_attach_vpp_store),
__ATTR_RO(blend_conflict),
__ATTR_RO(force_disable),
__ATTR(enable_hdmi_delay_normal_check,
0664,
enable_hdmi_delay_check_show,
enable_hdmi_delay_check_store),
__ATTR(hdmin_delay_count_debug,
0664,
hdmi_delay_debug_show,
NULL),
__ATTR(vd1_vd2_mux,
0664,
vd1_vd2_mux_show,
vd1_vd2_mux_store),
__ATTR(aisr_en,
0664,
aisr_en_show,
aisr_en_store),
__ATTR(reshape_output,
0664,
NULL,
reshape_output_store),
__ATTR(aisr_pps_auto_calc,
0664,
pps_auto_calc_show,
NULL),
__ATTR(ai_pq_disable,
0664,
ai_pq_disable_show,
ai_pq_disable_store),
__ATTR(ai_pq_debug,
0664,
ai_pq_debug_show,
ai_pq_debug_store),
__ATTR(ai_pq_value,
0664,
ai_pq_value_show,
ai_pq_value_store),
__ATTR(ai_pq_policy,
0664,
ai_pq_policy_show,
ai_pq_policy_store),
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
__ATTR(det_stb_cnt,
0664,
det_stb_cnt_show,
det_stb_cnt_store),
__ATTR(det_unstb_cnt,
0664,
det_unstb_cnt_show,
det_unstb_cnt_store),
__ATTR(tolrnc_cnt,
0664,
tolrnc_cnt_show,
tolrnc_cnt_store),
__ATTR(timer_filter_en,
0664,
timer_filter_en_show,
timer_filter_en_store),
__ATTR(aipq_set_policy,
0664,
aipq_set_policy_show,
aipq_set_policy_store),
__ATTR(color_th,
0664,
color_th_show,
color_th_store),
__ATTR(aisr_demo_en,
0664,
aisr_demo_en_show,
aisr_demo_en_store),
__ATTR(aisr_demo_axis,
0664,
aisr_demo_axis_show,
aisr_demo_axis_store),
__ATTR(power_ctrl,
0664,
power_ctrl_show,
power_ctrl_store),
#endif
__ATTR(frc_delay,
0664,
frc_delay_show,
NULL),
__ATTR(urgent_set,
0644,
vpu_module_urgent_show,
vpu_module_urgent_set),
__ATTR(aipq_dbg,
0644,
aipq_dbg_data_show,
aipq_dbg_data_store),
};
static struct class_attribute amvideo_poll_class_attrs[] = {
__ATTR_RO(frame_width),
__ATTR_RO(frame_height),
__ATTR_RO(vframe_states),
__ATTR_RO(video_state),
__ATTR_RO(primary_src_fmt),
__ATTR_RO(status_changed),
__ATTR_RO(frc_delay),
__ATTR_NULL
};
static struct class *amvideo_class;
static struct class *amvideo_poll_class;
static int video_attr_create(void)
{
int i;
int ret = 0;
/* create amvideo_class */
amvideo_class = class_create(THIS_MODULE, AMVIDEO_CLASS_NAME);
if (IS_ERR(amvideo_class)) {
pr_err("create amvideo_class fail\n");
return -1;
}
/* create amvideo class attr files */
for (i = 0; i < ARRAY_SIZE(amvideo_class_attrs); i++) {
if (class_create_file(amvideo_class,
&amvideo_class_attrs[i])) {
pr_err("create amvideo attribute %s fail\n",
amvideo_class_attrs[i].attr.name);
}
}
/* create amvideo_poll_class */
amvideo_poll_class = class_create(THIS_MODULE, AMVIDEO_POLL_CLASS_NAME);
if (IS_ERR(amvideo_poll_class)) {
pr_err("create amvideo_poll_class fail\n");
return -1;
}
/* create amvideo_poll class attr files */
for (i = 0; i < ARRAY_SIZE(amvideo_poll_class_attrs); i++) {
if (class_create_file(amvideo_poll_class,
&amvideo_poll_class_attrs[i])) {
pr_err("create amvideo_poll attribute %s fail\n",
amvideo_poll_class_attrs[i].attr.name);
}
}
pr_debug("create video attribute OK\n");
return ret;
}
#ifdef TV_REVERSE
static int vpp_axis_reverse(char *str)
{
char *ptr = str;
pr_info("%s: bootargs is %s\n", __func__, str);
if (strstr((const char *)ptr, "1"))
reverse = true;
else
reverse = false;
glayer_info[0].reverse = reverse;
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;
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);
if (vinfo->name)
strncpy(new_vmode, vinfo->name, sizeof(new_vmode) - 1);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
pr_info("DOLBY: %s: VOUT_EVENT_MODE_CHANGE\n",
__func__);
/* force send hdmi pkt in dv code */
/* to workaround pkt cleaned during hotplug */
if (is_dolby_vision_enable())
dolby_vision_set_toggle_flag(2);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
else
set_cur_hdr_policy(0xff);
#endif
#endif
break;
case VOUT_EVENT_OSD_PREBLEND_ENABLE:
break;
case VOUT_EVENT_OSD_DISP_AXIS:
break;
}
return 0;
}
static struct notifier_block vout_notifier = {
.notifier_call = vout_notify_callback,
};
static void vout_hook(void)
{
vout_register_client(&vout_notifier);
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;
if (vinfo->name)
strncpy(old_vmode, vinfo->name, sizeof(old_vmode) - 1);
if (vinfo->name)
strncpy(new_vmode, vinfo->name, sizeof(new_vmode) - 1);
}
#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, unreg_flag;
static struct vd_signal_info_s vd_signal;
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;
osd_vpp1_bld_ctrl_mask = p[3];
val = (p[2] & osd_vpp1_bld_ctrl_mask);
osd_vpp1_bld_ctrl = val;
osd_vpp2_bld_ctrl_mask = p[5];
val = (p[4] & osd_vpp2_bld_ctrl_mask);
osd_vpp2_bld_ctrl = val;
osd_vpp_bld_ctrl_update_mask = p[6];
val = (p[2] & osd_vpp_bld_ctrl_update_mask);
update_osd_vpp1_bld_ctrl = val;
val = (p[4] & osd_vpp_bld_ctrl_update_mask);
update_osd_vpp2_bld_ctrl = val;
if (!update_osd_vpp_misc)
update_osd_vpp_misc = true;
break;
case AMVIDEO_UPDATE_PREBLEND_MODE:
p = (u32 *)para;
osd_preblend_en = p[0];
break;
case AMVIDEO_UPDATE_SIGNAL_MODE:
memcpy(&vd_signal, para,
sizeof(struct vd_signal_info_s));
vd_signal_notifier_call_chain
(VIDEO_SIGNAL_TYPE_CHANGED,
&vd_signal);
break;
case AMVIDEO_UPDATE_VT_REG:
p = (u32 *)para;
val = p[0]; /* video tunnel id */
if (p[1] == 1) { /* path enable */
unreg_flag = atomic_read(&vt_unreg_flag);
if (unreg_flag > 0)
atomic_dec(&vt_unreg_flag);
} else { /* path disable */
hdmi_in_delay_maxmin_reset();
while (atomic_read(&video_inirq_flag) > 0)
schedule();
atomic_set(&vt_disable_video_done, 0);
atomic_inc(&vt_unreg_flag);
while (atomic_read(&vt_disable_video_done) > 0)
schedule();
}
pr_info("%s vt reg/unreg: id %d, state:%d\n",
__func__, val, p[1]);
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);
/*********************************************************/
struct device *get_video_device(void)
{
return amvideo_dev;
}
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),
MC_PU32("smooth_sync_enable", &smooth_sync_enable),
MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo),
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_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)
{
safe_switch_videolayer(0, false, false);
safe_switch_videolayer(1, false, false);
safe_switch_videolayer(2, false, false);
video_suspend = true;
pr_info("%s ok\n", __func__);
}
static void video_late_resume(struct early_suspend *h)
{
video_suspend_cycle = 0;
video_suspend = false;
log_out = 1;
pr_info("%s ok\n", __func__);
};
static struct early_suspend video_early_suspend_handler = {
.suspend = video_early_suspend,
.resume = video_late_resume,
};
#endif
static struct amvideo_device_data_s amvideo = {
.cpu_type = MESON_CPU_MAJOR_ID_COMPATIBALE,
.sr_reg_offt = 0xff,
.sr_reg_offt2 = 0xff,
.layer_support[0] = 0xff,
.layer_support[1] = 0xff,
.layer_support[2] = 0,
.afbc_support[0] = 0xff,
.afbc_support[1] = 0xff,
.afbc_support[2] = 0,
.pps_support[0] = 0xff,
.pps_support[1] = 0xff,
.pps_support[2] = 0,
.alpha_support[0] = 0xff,
.alpha_support[1] = 0xff,
.alpha_support[2] = 0,
.dv_support = 1,
.sr0_support = 0xff,
.sr1_support = 0xff,
.core_v_disable_width_max[0] = 0xff,
.core_v_disable_width_max[1] = 0xff,
.core_v_enable_width_max[0] = 0xff,
.core_v_enable_width_max[1] = 0xff,
.supscl_path = 0xff,
.fgrain_support[0] = 0,
.fgrain_support[1] = 0,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 0,
.has_hscaler_8tap[1] = 0,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 0,
.has_pre_hscaler_ntap[1] = 0,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 0,
.has_pre_vscaler_ntap[1] = 0,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 0xff,
.src_width_max[1] = 0xff,
.src_height_max[0] = 0xff,
.src_height_max[1] = 0xff,
.ofifo_size = 0xff,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
.has_vpp1 = 0,
.has_vpp2 = 0,
};
static struct amvideo_device_data_s amvideo_tm2_revb = {
.cpu_type = MESON_CPU_MAJOR_ID_TM2_REVB,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 1,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 0,
.alpha_support[1] = 0,
.alpha_support[2] = 0,
.dv_support = 1,
.sr0_support = 1,
.sr1_support = 1,
.core_v_disable_width_max[0] = 2048,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 1024,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_PPS_CORE1,
.fgrain_support[0] = 1,
.fgrain_support[1] = 1,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 0,
.has_hscaler_8tap[1] = 0,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 0,
.has_pre_hscaler_ntap[1] = 0,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 0,
.has_pre_vscaler_ntap[1] = 0,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 4096,
.src_width_max[1] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
.has_vpp1 = 0,
.has_vpp2 = 0,
};
static struct amvideo_device_data_s amvideo_sc2 = {
.cpu_type = MESON_CPU_MAJOR_ID_SC2_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 1,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 1,
.alpha_support[1] = 1,
.alpha_support[2] = 0,
.dv_support = 1,
.sr0_support = 1,
.sr1_support = 0,
.core_v_disable_width_max[0] = 4096,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 2048,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_BEFORE_PPS,
.fgrain_support[0] = 1,
.fgrain_support[1] = 1,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 1,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 1,
.has_pre_hscaler_ntap[1] = 1,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 0,
.has_pre_vscaler_ntap[1] = 0,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 4096,
.src_width_max[1] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
.has_vpp1 = 0,
.has_vpp2 = 0,
};
static struct amvideo_device_data_s amvideo_t5 = {
.cpu_type = MESON_CPU_MAJOR_ID_T5_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 0,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 0,
.pps_support[2] = 0,
.alpha_support[0] = 0,
.alpha_support[1] = 0,
.alpha_support[2] = 0,
.dv_support = 0,
.sr0_support = 1,
.sr1_support = 1,
.core_v_disable_width_max[0] = 2048,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 1024,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_PPS_CORE1,
.fgrain_support[0] = 0,
.fgrain_support[1] = 0,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 0,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 1,
.has_pre_hscaler_ntap[1] = 0,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 0,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 4096,
.src_width_max[1] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
.has_vpp1 = 0,
.has_vpp2 = 0,
};
static struct amvideo_device_data_s amvideo_t5d = {
.cpu_type = MESON_CPU_MAJOR_ID_T5D_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 0,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 0,
.alpha_support[1] = 0,
.alpha_support[2] = 0,
.dv_support = 0,
.sr0_support = 0,
.sr1_support = 1,
.core_v_disable_width_max[0] = 1024,
.core_v_disable_width_max[1] = 2048,
.core_v_enable_width_max[0] = 1024,
.core_v_enable_width_max[1] = 1024,
.supscl_path = PPS_CORE1_CM,
.fgrain_support[0] = 0,
.fgrain_support[1] = 0,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 0,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 1,
.has_pre_hscaler_ntap[1] = 0,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 0,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 2048,
.src_width_max[1] = 2048,
.src_height_max[0] = 1080,
.src_height_max[1] = 1080,
.ofifo_size = 0x780,
.afbc_conv_lbuf_len[0] = 0x80,
.afbc_conv_lbuf_len[1] = 0x80,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
.has_vpp1 = 0,
.has_vpp2 = 0,
};
static struct amvideo_device_data_s amvideo_t7 = {
.cpu_type = MESON_CPU_MAJOR_ID_T7_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 1,
.afbc_support[0] = 1,
.afbc_support[1] = 1,
.afbc_support[2] = 1,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 1,
.alpha_support[0] = 1,
.alpha_support[1] = 1,
.alpha_support[2] = 1,
.dv_support = 1,
.sr0_support = 1,
.sr1_support = 0,
.core_v_disable_width_max[0] = 4096,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 2048,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_AFTER_PPS,
.fgrain_support[0] = 1,
.fgrain_support[1] = 1,
.fgrain_support[2] = 1,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 1,
.has_hscaler_8tap[2] = 1,
.has_pre_hscaler_ntap[0] = 2,
.has_pre_hscaler_ntap[1] = 2,
.has_pre_hscaler_ntap[2] = 2,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 1,
.has_pre_vscaler_ntap[2] = 1,
.src_width_max[0] = 4096,
.src_width_max[1] = 4096,
.src_width_max[2] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 2160,
.src_height_max[2] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.afbc_conv_lbuf_len[2] = 0x100,
.mif_linear = 1,
.t7_display = 1,
.max_vd_layers = 3,
.has_vpp1 = 1,
.has_vpp2 = 1,
};
static struct amvideo_device_data_s amvideo_s4 = {
.cpu_type = MESON_CPU_MAJOR_ID_S4_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 1,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 1,
.alpha_support[1] = 1,
.alpha_support[2] = 0,
.dv_support = 0,
.sr0_support = 1,
.sr1_support = 0,
.core_v_disable_width_max[0] = 4096,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 2048,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_BEFORE_PPS,
.fgrain_support[0] = 0,
.fgrain_support[1] = 0,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 1,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 1,
.has_pre_hscaler_ntap[1] = 1,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 1,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 4096,
.src_width_max[1] = 4096,
.src_width_max[2] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 2160,
.src_height_max[2] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
};
static struct amvideo_device_data_s amvideo_t5d_revb = {
.cpu_type = MESON_CPU_MAJOR_ID_T5D_REVB_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 0,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 0,
.alpha_support[1] = 0,
.alpha_support[2] = 0,
.dv_support = 0,
.sr0_support = 0,
.sr1_support = 1,
.core_v_disable_width_max[0] = 1024,
.core_v_disable_width_max[1] = 2048,
.core_v_enable_width_max[0] = 1024,
.core_v_enable_width_max[1] = 1024,
.supscl_path = PPS_CORE1_CM,
.fgrain_support[0] = 0,
.fgrain_support[1] = 0,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 0,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 1,
.has_pre_hscaler_ntap[1] = 0,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 0,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 2048,
.src_width_max[1] = 2048,
.src_height_max[0] = 1080,
.src_height_max[1] = 1080,
.ofifo_size = 0x780,
.afbc_conv_lbuf_len[0] = 0x80,
.afbc_conv_lbuf_len[1] = 0x80,
.mif_linear = 0,
.t7_display = 0,
.max_vd_layers = 2,
};
static struct amvideo_device_data_s amvideo_t3 = {
.cpu_type = MESON_CPU_MAJOR_ID_T3_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 1,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 1,
.alpha_support[1] = 1,
.alpha_support[2] = 0,
.dv_support = 1,
.sr0_support = 1,
.sr1_support = 1,
.core_v_disable_width_max[0] = 2048,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 1024,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_PPS_CORE1,
.fgrain_support[0] = 1,
.fgrain_support[1] = 1,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 1,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 2,
.has_pre_hscaler_ntap[1] = 2,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 1,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 4096,
.src_width_max[1] = 4096,
.src_width_max[2] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 2160,
.src_height_max[2] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x100,
.mif_linear = 1,
.t7_display = 1,
.max_vd_layers = 2,
.has_vpp1 = 1,
.has_vpp2 = 0,
};
static struct amvideo_device_data_s amvideo_t5w = {
.cpu_type = MESON_CPU_MAJOR_ID_T5W_,
.sr_reg_offt = 0x1e00,
.sr_reg_offt2 = 0x1f80,
.layer_support[0] = 1,
.layer_support[1] = 1,
.layer_support[2] = 0,
.afbc_support[0] = 1,
.afbc_support[1] = 1,
.afbc_support[2] = 0,
.pps_support[0] = 1,
.pps_support[1] = 1,
.pps_support[2] = 0,
.alpha_support[0] = 1,
.alpha_support[1] = 1,
.alpha_support[2] = 0,
.dv_support = 1,
.sr0_support = 1,
.sr1_support = 1,
.core_v_disable_width_max[0] = 2048,
.core_v_disable_width_max[1] = 4096,
.core_v_enable_width_max[0] = 1024,
.core_v_enable_width_max[1] = 2048,
.supscl_path = CORE0_PPS_CORE1,
.fgrain_support[0] = 1,
.fgrain_support[1] = 1,
.fgrain_support[2] = 0,
.has_hscaler_8tap[0] = 1,
.has_hscaler_8tap[1] = 1,
.has_hscaler_8tap[2] = 0,
.has_pre_hscaler_ntap[0] = 2,
.has_pre_hscaler_ntap[1] = 2,
.has_pre_hscaler_ntap[2] = 0,
.has_pre_vscaler_ntap[0] = 1,
.has_pre_vscaler_ntap[1] = 1,
.has_pre_vscaler_ntap[2] = 0,
.src_width_max[0] = 4096,
.src_width_max[1] = 2048,
.src_width_max[2] = 4096,
.src_height_max[0] = 2160,
.src_height_max[1] = 1080,
.src_height_max[2] = 2160,
.ofifo_size = 0x1000,
.afbc_conv_lbuf_len[0] = 0x100,
.afbc_conv_lbuf_len[1] = 0x80,
.mif_linear = 1,
.t7_display = 1,
.max_vd_layers = 2,
.has_vpp1 = 1,
.has_vpp2 = 0,
};
static struct video_device_hw_s legcy_dev_property = {
.vd2_independ_blend_ctrl = 0,
.aisr_support = 0,
.frc_support = 0,
.sr_in_size = 0,
};
static struct video_device_hw_s t3_dev_property = {
.vd2_independ_blend_ctrl = 1,
.aisr_support = 1,
.frc_support = 1,
/* aisr reverse workaround for t3*/
.di_hf_y_reverse = 1,
.sr_in_size = 1,
};
static struct video_device_hw_s t5w_dev_property = {
.vd2_independ_blend_ctrl = 1,
.aisr_support = 0,
.frc_support = 0,
.di_hf_y_reverse = 0,
.sr_in_size = 1,
};
static const struct of_device_id amlogic_amvideom_dt_match[] = {
{
.compatible = "amlogic, amvideom",
.data = &amvideo,
},
{
.compatible = "amlogic, amvideom-tm2-revb",
.data = &amvideo_tm2_revb,
},
{
.compatible = "amlogic, amvideom-sc2",
.data = &amvideo_sc2,
},
{
.compatible = "amlogic, amvideom-t5",
.data = &amvideo_t5,
},
{
.compatible = "amlogic, amvideom-t5d",
.data = &amvideo_t5d,
},
{
.compatible = "amlogic, amvideom-t7",
.data = &amvideo_t7,
},
{
.compatible = "amlogic, amvideom-s4",
.data = &amvideo_s4,
},
{
.compatible = "amlogic, amvideom-t5d-revb",
.data = &amvideo_t5d_revb,
},
{
.compatible = "amlogic, amvideom-t3",
.data = &amvideo_t3,
},
{
.compatible = "amlogic, amvideom-t5w",
.data = &amvideo_t5w,
},
{}
};
bool is_meson_tm2_revb(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_TM2_REVB)
return true;
else
return false;
}
bool video_is_meson_sc2_cpu(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_SC2_)
return true;
else
return false;
}
bool video_is_meson_t5d_cpu(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_T5D_)
return true;
else
return false;
}
bool video_is_meson_t7_cpu(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_T7_)
return true;
else
return false;
}
bool video_is_meson_s4_cpu(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_S4_)
return true;
else
return false;
}
bool video_is_meson_t5d_revb_cpu(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_T5D_REVB_)
return true;
else
return false;
}
bool video_is_meson_t3_cpu(void)
{
if (amvideo_meson_dev.cpu_type ==
MESON_CPU_MAJOR_ID_T3_)
return true;
else
return false;
}
bool has_hscaler_8tap(u8 layer_id)
{
if (amvideo_meson_dev.has_hscaler_8tap[layer_id])
return true;
else
return false;
}
bool has_pre_hscaler_ntap(u8 layer_id)
{
if (amvideo_meson_dev.has_pre_hscaler_ntap[layer_id])
return true;
else
return false;
}
bool has_pre_hscaler_8tap(u8 layer_id)
{
if (amvideo_meson_dev.has_pre_hscaler_ntap[layer_id] == 2)
return true;
else
return false;
}
bool has_pre_vscaler_ntap(u8 layer_id)
{
if (amvideo_meson_dev.has_pre_vscaler_ntap[layer_id])
return true;
else
return false;
}
static void video_cap_set(struct amvideo_device_data_s *p_amvideo)
{
if (p_amvideo->cpu_type ==
MESON_CPU_MAJOR_ID_COMPATIBALE) {
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 {
/* g12a, g12b, sm1 */
layer_cap =
LAYER1_AFBC |
LAYER1_SCALER |
LAYER1_AVAIL |
LAYER0_AFBC |
LAYER0_SCALER |
LAYER0_AVAIL;
}
} else {
if (p_amvideo->layer_support[0])
layer_cap |= LAYER0_AVAIL;
if (p_amvideo->layer_support[1])
layer_cap |= LAYER1_AVAIL;
if (p_amvideo->layer_support[2])
layer_cap |= LAYER2_AVAIL;
if (p_amvideo->afbc_support[0])
layer_cap |= LAYER0_AFBC;
if (p_amvideo->afbc_support[1])
layer_cap |= LAYER1_AFBC;
if (p_amvideo->afbc_support[2])
layer_cap |= LAYER2_AFBC;
if (p_amvideo->pps_support[0])
layer_cap |= LAYER0_SCALER;
/* remove the vd2 support cap for upper layer */
if (p_amvideo->pps_support[1] &&
(p_amvideo->cpu_type != MESON_CPU_MAJOR_ID_T5D_REVB_ ||
!vd1_vd2_mux))
layer_cap |= LAYER1_SCALER;
if (p_amvideo->pps_support[2])
layer_cap |= LAYER2_SCALER;
if (p_amvideo->alpha_support[0])
layer_cap |= LAYER0_ALPHA;
if (p_amvideo->alpha_support[1])
layer_cap |= LAYER1_ALPHA;
if (p_amvideo->alpha_support[2])
layer_cap |= LAYER2_ALPHA;
layer_cap |= ((u32)vd_layer[0].vpp_index << LAYER0_VPP |
(u32)vd_layer[1].vpp_index << LAYER1_VPP |
(u32)vd_layer[2].vpp_index << LAYER2_VPP);
}
pr_debug("%s cap:%x, ptype:%d\n", __func__, layer_cap, p_amvideo->cpu_type);
}
static void set_rdma_func_handler(void)
{
cur_dev->rdma_func[0].rdma_rd =
VSYNC_RD_MPEG_REG;
cur_dev->rdma_func[0].rdma_wr =
VSYNC_WR_MPEG_REG;
cur_dev->rdma_func[0].rdma_wr_bits =
VSYNC_WR_MPEG_REG_BITS;
cur_dev->rdma_func[1].rdma_rd =
VSYNC_RD_MPEG_REG_VPP1;
cur_dev->rdma_func[1].rdma_wr =
VSYNC_WR_MPEG_REG_VPP1;
cur_dev->rdma_func[1].rdma_wr_bits =
VSYNC_WR_MPEG_REG_BITS_VPP1;
cur_dev->rdma_func[2].rdma_rd =
VSYNC_RD_MPEG_REG_VPP2;
cur_dev->rdma_func[2].rdma_wr =
VSYNC_WR_MPEG_REG_VPP2;
cur_dev->rdma_func[2].rdma_wr_bits =
VSYNC_WR_MPEG_REG_BITS_VPP2;
cur_dev->rdma_func[3].rdma_rd =
PRE_VSYNC_RD_MPEG_REG;
cur_dev->rdma_func[3].rdma_wr =
PRE_VSYNC_WR_MPEG_REG;
cur_dev->rdma_func[3].rdma_wr_bits =
PRE_VSYNC_WR_MPEG_REG_BITS;
}
static int amvideom_probe(struct platform_device *pdev)
{
int ret = 0;
int i, j;
int vdtemp = -1;
const void *prop;
int display_device_cnt = 1;
if (pdev->dev.of_node) {
const struct of_device_id *match;
struct amvideo_device_data_s *amvideo_meson;
struct device_node *of_node = pdev->dev.of_node;
match = of_match_node(amlogic_amvideom_dt_match, of_node);
if (match) {
amvideo_meson =
(struct amvideo_device_data_s *)match->data;
if (amvideo_meson) {
memcpy(&amvideo_meson_dev, amvideo_meson,
sizeof(struct amvideo_device_data_s));
} else {
pr_err("%s data NOT match\n", __func__);
return -ENODEV;
}
} else {
pr_err("%s NOT match\n", __func__);
return -ENODEV;
}
}
if (amvideo_meson_dev.cpu_type == MESON_CPU_MAJOR_ID_T3_) {
memcpy(&amvideo_meson_dev.dev_property, &t3_dev_property,
sizeof(struct video_device_hw_s));
aisr_en = 1;
cur_dev->power_ctrl = true;
WRITE_VCBUS_REG(VPU_AXI_CACHE, 0x11111);
set_vpu_super_urgent(FRC0_R, 3, 3);
set_vpu_super_urgent(FRC0_W, 3, 3);
set_vpu_super_urgent(FRC1_R, 2, 2);
set_vpu_super_urgent(FRC1_W, 2, 2);
set_vpu_super_urgent(FRC2_R, 3, 7);
set_vpu_super_urgent(VPU0_R, 3, 5);
set_vpu_super_urgent(VPU0_W, 3, 5);
set_vpu_super_urgent(VPU1_R, 0, 0);
set_vpu_super_urgent(VPU1_W, 0, 0);
set_vpu_super_urgent(VPU2_R, 3, 5);
} else if (amvideo_meson_dev.cpu_type == MESON_CPU_MAJOR_ID_T5W_) {
memcpy(&amvideo_meson_dev.dev_property, &t5w_dev_property,
sizeof(struct video_device_hw_s));
cur_dev->power_ctrl = true;
} else {
memcpy(&amvideo_meson_dev.dev_property, &legcy_dev_property,
sizeof(struct video_device_hw_s));
}
if (amvideo_meson_dev.max_vd_layers > MAX_VD_LAYERS)
return -EINVAL;
vdtemp = of_property_read_u32(pdev->dev.of_node, "vd1_vd2_mux",
&vd1_vd2_mux_dts);
if (vdtemp < 0)
vd1_vd2_mux_dts = 1;
set_rdma_func_handler();
video_early_init(&amvideo_meson_dev);
video_hw_init();
prop = of_get_property(pdev->dev.of_node, "display_device_cnt", NULL);
if (prop)
display_device_cnt = of_read_ulong(prop, 1);
prop = of_get_property(pdev->dev.of_node, "vpp2_layer_count", NULL);
if (prop && display_device_cnt >= 3) {
int layer_count;
layer_count = of_read_ulong(prop, 1);
if (layer_count >= 2) {
pr_err("vpp2 only support one video layer\n");
} else if (layer_count == 1) {
vd_layer[2].vpp_index = VPP2;
vd_layer_vpp[1].vpp_index = VPP2;
vd_layer_vpp[1].layer_id = 2;
}
}
prop = of_get_property(pdev->dev.of_node, "vpp1_layer_count", NULL);
if (prop && display_device_cnt >= 2) {
int layer_count;
layer_count = of_read_ulong(prop, 1);
if (layer_count >= 2) {
pr_err("vpp1 only support one video layer\n");
} else if (layer_count == 1) {
vd_layer[1].vpp_index = VPP1;
vd_layer_vpp[0].vpp_index = VPP1;
vd_layer_vpp[0].layer_id = 1;
}
}
video_cap_set(&amvideo_meson_dev);
video_suspend = false;
video_suspend_cycle = 0;
log_out = 1;
safe_switch_videolayer(0, false, false);
safe_switch_videolayer(1, false, false);
safe_switch_videolayer(2, false, false);
/* 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);
if (amvideo_meson_dev.cpu_type == MESON_CPU_MAJOR_ID_SC2_ ||
amvideo_meson_dev.has_vpp1) {
/* get interrupt resource */
video_vsync_viu2 = platform_get_irq_byname(pdev, "vsync_viu2");
if (video_vsync_viu2 == -ENXIO)
pr_info("cannot get amvideom viu2 irq resource\n");
else
pr_info("amvideom vsync viu2 irq: %d\n",
video_vsync_viu2);
/* vpp1 used then register rdma channel */
if (display_device_cnt == 2)
vpp1_vsync_rdma_register();
}
if (amvideo_meson_dev.has_vpp2) {
/* get interrupt resource */
video_vsync_viu3 = platform_get_irq_byname(pdev, "vsync_viu3");
if (video_vsync_viu3 == -ENXIO)
pr_info("cannot get amvideom viu3 irq resource\n");
else
pr_info("amvideom vsync viu3 irq: %d\n",
video_vsync_viu3);
/* vpp2 used then register rdma channel */
if (display_device_cnt == 3)
vpp2_vsync_rdma_register();
}
if (amvideo_meson_dev.dev_property.frc_support) {
video_pre_vsync = platform_get_irq_byname(pdev, "pre_vsync");
if (video_pre_vsync == -ENXIO)
pr_info("cannot get amvideom video_pre_vsync irq resource\n");
else
pr_info("amvideom video pre vsync: %d\n",
video_pre_vsync);
pre_vsync_rdma_register();
}
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
register_early_suspend(&video_early_suspend_handler);
#endif
video_keeper_init();
for (i = 0; i < AI_SCENES_MAX; i++) {
vpp_scenes[i].pq_scenes = (enum ai_scenes)i;
for (j = 0; j < SCENES_VALUE; j++)
vpp_scenes[i].pq_values[j] = vpp_pq_data[i][j];
}
return ret;
}
static int amvideom_remove(struct platform_device *pdev)
{
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
unregister_early_suspend(&video_early_suspend_handler);
#endif
video_keeper_exit();
return 0;
}
static struct platform_driver amvideom_driver = {
.probe = amvideom_probe,
.remove = amvideom_remove,
.driver = {
.name = "amvideom",
.of_match_table = amlogic_amvideom_dt_match,
},
};
int __init video_init(void)
{
int r = 0;
/*
*#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 !defined(CONFIG_ARCH_MESON3) && !defined(CONFIG_ARCH_MESON6) */
if (platform_driver_register(&amvideom_driver)) {
pr_info("failed to amvideom driver!\n");
return -ENODEV;
}
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
r = video_attr_create();
if (r < 0) {
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;
}
/* 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;
}
init_waitqueue_head(&amvideo_trick_wait);
init_waitqueue_head(&amvideo_prop_change_wait);
#ifdef CONFIG_AM_VOUT
vout_hook();
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
memset(dispbuf_to_put, 0, sizeof(dispbuf_to_put));
memset(pipbuf_to_put, 0, sizeof(pipbuf_to_put));
memset(pipbuf2_to_put, 0, sizeof(pipbuf2_to_put));
#endif
memset(recycle_buf, 0, sizeof(recycle_buf));
memset(recycle_cnt, 0, sizeof(recycle_cnt));
gvideo_recv[0] = create_video_receiver
("video_render.0", VFM_PATH_VIDEO_RENDER0);
gvideo_recv[1] = create_video_receiver
("video_render.1", VFM_PATH_VIDEO_RENDER1);
gvideo_recv[2] = create_video_receiver
("video_render.2", VFM_PATH_VIDEO_RENDER2);
/* for multi vpp */
gvideo_recv_vpp[0] = create_video_receiver
("video_render.5", VFM_PATH_VIDEO_RENDER5);
gvideo_recv_vpp[1] = create_video_receiver
("video_render.6", VFM_PATH_VIDEO_RENDER6);
vsync_fiq_up();
vf_receiver_init
(&video_vf_recv, RECEIVER_NAME,
&video_vf_receiver, NULL);
vf_reg_receiver(&video_vf_recv);
vf_receiver_init
(&videopip_vf_recv, RECEIVERPIP_NAME,
&videopip_vf_receiver, NULL);
vf_reg_receiver(&videopip_vf_recv);
vf_receiver_init
(&videopip2_vf_recv, RECEIVERPIP2_NAME,
&videopip2_vf_receiver, NULL);
vf_reg_receiver(&videopip2_vf_recv);
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;
}
void __exit video_exit(void)
{
video_debugfs_exit();
vf_unreg_receiver(&video_vf_recv);
vf_unreg_receiver(&videopip_vf_recv);
vf_unreg_receiver(&videopip2_vf_recv);
safe_switch_videolayer(0, false, false);
safe_switch_videolayer(1, false, false);
safe_switch_videolayer(2, false, false);
#ifdef CONFIG_AMLOGIC_MEDIA_SECURITY
secure_unregister(VIDEO_MODULE);
#endif
vsync_fiq_down();
if (gvideo_recv[0])
destroy_video_receiver(gvideo_recv[0]);
gvideo_recv[0] = NULL;
if (gvideo_recv[1])
destroy_video_receiver(gvideo_recv[1]);
gvideo_recv[1] = NULL;
if (gvideo_recv[2])
destroy_video_receiver(gvideo_recv[2]);
gvideo_recv[2] = NULL;
/* for multi vpp */
if (gvideo_recv_vpp[0])
destroy_video_receiver(gvideo_recv_vpp[0]);
gvideo_recv_vpp[0] = NULL;
if (gvideo_recv_vpp[1])
destroy_video_receiver(gvideo_recv_vpp[1]);
gvideo_recv_vpp[1] = NULL;
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, int, 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_param_named(video_vsync_enter_line_max,
vsync_enter_line_max, int, 0664);
module_param_named(video_vsync_exit_line_max,
vsync_exit_line_max, int, 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, int, 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, int, 0664);
MODULE_PARM_DESC(step_enable, "\n step_enable\n");
module_param(step_flag, int, 0664);
MODULE_PARM_DESC(step_flag, "\n step_flag\n");
/*arch_initcall(video_early_init);*/
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);
MODULE_PARM_DESC(vsync_count, "\n vsync_count\n");
module_param(vsync_count, 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(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_param(reverse, bool, 0644);
MODULE_PARM_DESC(reverse, "reverse /disable reverse");
MODULE_PARM_DESC(toggle_count, "\n toggle count\n");
module_param(toggle_count, uint, 0664);
MODULE_PARM_DESC(stop_update, "\n stop_update\n");
module_param(stop_update, uint, 0664);
//MODULE_DESCRIPTION("AMLOGIC video output driver");
//MODULE_LICENSE("GPL");
//MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");