blob: 2d448d2311029976facd1924e0762147d1e463d6 [file] [log] [blame]
/*
* drivers/amlogic/media/video_sink/video.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/amlogic/major.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/ctype.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/frame_sync/timestamp.h>
#include <linux/amlogic/media/frame_sync/tsync.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/amlogic/media/utils/amstream.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/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 <trace/events/meson_atrace.h>
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
#include <linux/amlogic/media/amvecm/amvecm.h>
#endif
#include <linux/amlogic/media/utils/vdec_reg.h>
#ifdef CONFIG_PM
#include <linux/delay.h>
#include <linux/pm.h>
#endif
#include <linux/amlogic/media/registers/register.h>
#include <linux/uaccess.h>
#include <linux/amlogic/media/utils/amports_config.h>
#include <linux/amlogic/media/vpu/vpu.h>
#include "videolog.h"
#ifdef CONFIG_AMLOGIC_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>
#include "linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h"
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
#define DISPLAY_CANVAS_BASE_INDEX2 0x10
#define DISPLAY_CANVAS_MAX_INDEX2 0x15
#include "../common/rdma/rdma.h"
#endif
#include <linux/amlogic/media/video_sink/video.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../common/vfm/vfm.h"
#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
#include <linux/amlogic/pm.h>
#endif
#define VIDEO_PIP
static u32 osd_vpp_misc;
static u32 osd_vpp_misc_mask;
static bool update_osd_vpp_misc;
int video_vsync = -ENXIO;
/*global video manage cmd. */
static bool legacy_vpp = true;
#define DEBUG_TMP 0
static int video_global_output = 1;
/* video_pause_global: 0 is play, 1 is pause, 2 is invalid */
static int video_pause_global = 1;
#ifdef CONFIG_GE2D_KEEP_FRAME
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
/* #include <mach/mod_gate.h> */
/* #endif */
/* #include "mach/meson-secure.h" */
#endif
#if 1
/*TODO for logo*/
struct platform_resource_s {
char name[10];
int mem_start;
int mem_end;
};
#endif
struct video_frame_detect_s {
u32 interrupt_count;
u32 start_receive_count;
};
static int debugflags;
static int output_fps;
static u32 omx_pts;
static u32 omx_pts_set_index;
static bool omx_run;
static u32 omx_version = 3;
#define OMX_PTS_DV_DEFAULT_UPPER 2500
#define OMX_PTS_DV_DEFAULT_LOWER -1600
static int omx_pts_interval_upper = 11000;
static int omx_pts_interval_lower = -5500;
static int omx_pts_dv_upper = OMX_PTS_DV_DEFAULT_UPPER;
static int omx_pts_dv_lower = OMX_PTS_DV_DEFAULT_LOWER;
static int omx_pts_set_from_hwc_count;
static bool omx_check_previous_session;
static u32 omx_cur_session = 0xffffffff;
static int drop_frame_count;
#define OMX_MAX_COUNT_RESET_SYSTEMTIME 2
static int receive_frame_count;
static int display_frame_count;
static int omx_need_drop_frame_num;
static bool omx_drop_done;
static bool video_start_post;
static bool videopeek;
static bool nopostvideostart;
static struct video_frame_detect_s video_frame_detect;
/*----omx_info bit0: keep_last_frame, bit1~31: unused----*/
static u32 omx_info = 0x1;
#define ENABLE_UPDATE_HDR_FROM_USER 0
#if ENABLE_UPDATE_HDR_FROM_USER
static struct vframe_master_display_colour_s vf_hdr;
static bool has_hdr_info;
#endif
static DEFINE_MUTEX(omx_mutex);
#define DURATION_GCD 750
static bool bypass_cm;
static bool bypass_pps = true;
/*For 3D usage ----0: mbx 1: tv */
bool platform_type = 1;
/* for bit depth setting. */
int bit_depth_flag = 8;
bool omx_secret_mode;
#define DEBUG_FLAG_FFPLAY (1<<0)
#define DEBUG_FLAG_CALC_PTS_INC (1<<1)
#define RECEIVER_NAME "amvideo"
static s32 amvideo_poll_major;
/*static s8 dolby_first_delay;*/ /* for bug 145902 */
static int video_receiver_event_fun(int type, void *data, void *);
static const struct vframe_receiver_op_s video_vf_receiver = {
.event_cb = video_receiver_event_fun
};
static struct vframe_receiver_s video_vf_recv;
#ifdef VIDEO_PIP
#define RECEIVERPIP_NAME "videopip"
static int pip_receiver_event_fun(int type, void *data, void *);
static const struct vframe_receiver_op_s videopip_vf_receiver = {
.event_cb = pip_receiver_event_fun
};
static struct vframe_receiver_s videopip_vf_recv;
static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par;
static struct vpp_frame_par_s pip_frame_parms[2];
static struct vframe_s *cur_pipbuf;
static struct vframe_s local_pip;
//int _videopip_set_disable(u32 val);
#endif
static struct device *amvideo_dev;
static struct device *amvideo_poll_dev;
static u32 cur_width;
static u32 cur_height;
#define DRIVER_NAME "amvideo"
#define MODULE_NAME "amvideo"
#define DEVICE_NAME "amvideo"
#ifdef CONFIG_AML_VSYNC_FIQ_ENABLE
#define FIQ_VSYNC
#endif
/* #define SLOW_SYNC_REPEAT */
/* #define INTERLACE_FIELD_MATCH_PROCESS */
bool disable_slow_sync;
#ifdef INTERLACE_FIELD_MATCH_PROCESS
#define FIELD_MATCH_THRESHOLD 10
static int field_matching_count;
#endif
#define M_PTS_SMOOTH_MAX 45000
#define M_PTS_SMOOTH_MIN 2250
#define M_PTS_SMOOTH_ADJUST 900
static u32 underflow;
static u32 next_peek_underflow;
#define VIDEO_ENABLE_STATE_IDLE 0
#define VIDEO_ENABLE_STATE_ON_REQ 1
#define VIDEO_ENABLE_STATE_ON_PENDING 2
#define VIDEO_ENABLE_STATE_OFF_REQ 3
static DEFINE_SPINLOCK(video_onoff_lock);
static int video_onoff_state = VIDEO_ENABLE_STATE_IDLE;
static u32 video_onoff_time;
static DEFINE_SPINLOCK(video2_onoff_lock);
static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE;
static u32 hdmiin_frame_check;
static u32 hdmiin_frame_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;
#ifdef FIQ_VSYNC
#define BRIDGE_IRQ INT_TIMER_C
#define BRIDGE_IRQ_SET() WRITE_CBUS_REG(ISA_TIMERC, 1)
#endif
#define VD1_MEM_POWER_ON() \
do { \
unsigned long flags; \
spin_lock_irqsave(&delay_work_lock, flags); \
vpu_delay_work_flag &= ~VPU_DELAYWORK_MEM_POWER_OFF_VD1; \
spin_unlock_irqrestore(&delay_work_lock, flags); \
switch_vpu_mem_pd_vmod(VPU_VIU_VD1, VPU_MEM_POWER_ON); \
switch_vpu_mem_pd_vmod(VPU_AFBC_DEC, VPU_MEM_POWER_ON); \
switch_vpu_mem_pd_vmod(VPU_DI_POST, VPU_MEM_POWER_ON); \
if (!legacy_vpp) \
switch_vpu_mem_pd_vmod( \
VPU_VD1_SCALE, VPU_MEM_POWER_ON); \
} while (0)
#define VD2_MEM_POWER_ON() \
do { \
unsigned long flags; \
spin_lock_irqsave(&delay_work_lock, flags); \
vpu_delay_work_flag &= ~VPU_DELAYWORK_MEM_POWER_OFF_VD2; \
spin_unlock_irqrestore(&delay_work_lock, flags); \
switch_vpu_mem_pd_vmod(VPU_VIU_VD2, VPU_MEM_POWER_ON); \
switch_vpu_mem_pd_vmod(VPU_AFBC_DEC1, VPU_MEM_POWER_ON); \
if (!legacy_vpp) \
switch_vpu_mem_pd_vmod( \
VPU_VD2_SCALE, VPU_MEM_POWER_ON); \
} while (0)
#define VD1_MEM_POWER_OFF() \
do { \
unsigned long flags; \
spin_lock_irqsave(&delay_work_lock, flags); \
vpu_delay_work_flag |= VPU_DELAYWORK_MEM_POWER_OFF_VD1; \
vpu_mem_power_off_count = VPU_MEM_POWEROFF_DELAY; \
spin_unlock_irqrestore(&delay_work_lock, flags); \
} while (0)
#define VD2_MEM_POWER_OFF() \
do { \
unsigned long flags; \
spin_lock_irqsave(&delay_work_lock, flags); \
vpu_delay_work_flag |= VPU_DELAYWORK_MEM_POWER_OFF_VD2; \
vpu_mem_power_off_count = VPU_MEM_POWEROFF_DELAY; \
spin_unlock_irqrestore(&delay_work_lock, flags); \
} while (0)
#define VIDEO_LAYER_ON() \
do { \
unsigned long flags; \
spin_lock_irqsave(&video_onoff_lock, flags); \
video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \
video_enabled = 1; \
video_status_saved = 1; \
spin_unlock_irqrestore(&video_onoff_lock, flags); \
} while (0)
#define VIDEO_LAYER_OFF() \
do { \
unsigned long flags; \
spin_lock_irqsave(&video_onoff_lock, flags); \
video_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \
video_enabled = 0; \
video_status_saved = 0; \
spin_unlock_irqrestore(&video_onoff_lock, flags); \
} while (0)
#define VIDEO_LAYER2_ON() \
do { \
unsigned long flags; \
spin_lock_irqsave(&video2_onoff_lock, flags); \
video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \
video2_enabled = 1; \
video2_status_saved = 1; \
spin_unlock_irqrestore(&video2_onoff_lock, flags); \
} while (0)
#define VIDEO_LAYER2_OFF() \
do { \
unsigned long flags; \
spin_lock_irqsave(&video2_onoff_lock, flags); \
video2_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \
video2_enabled = 0; \
video2_status_saved = 0; \
spin_unlock_irqrestore(&video2_onoff_lock, flags); \
} while (0)
#define EnableVideoLayer() \
do { \
VD1_MEM_POWER_ON(); \
VIDEO_LAYER_ON(); \
} while (0)
#define EnableVideoLayer2() \
do { \
VD2_MEM_POWER_ON(); \
VIDEO_LAYER2_ON(); \
} while (0)
#define VSYNC_EnableVideoLayer2() \
do { \
VD2_MEM_POWER_ON(); \
VSYNC_WR_MPEG_REG(VPP_MISC + cur_dev->vpp_off, \
READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) |\
VPP_VD2_PREBLEND | (0x1ff << VPP_VD2_ALPHA_BIT)); \
} while (0)
#define DisableVideoLayer() \
do { \
CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \
VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND); \
if (!legacy_vpp) { \
WRITE_VCBUS_REG( \
VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); \
} \
WRITE_VCBUS_REG(AFBC_ENABLE, 0);\
VIDEO_LAYER_OFF(); \
VD1_MEM_POWER_OFF(); \
if (debug_flag & DEBUG_FLAG_BLACKOUT) { \
pr_info("DisableVideoLayer()\n"); \
} \
} while (0)
#define DisableVideoLayer_NoDelay() \
do { \
CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \
VPP_VD1_PREBLEND | VPP_VD2_PREBLEND|\
VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND); \
if (!legacy_vpp) { \
WRITE_VCBUS_REG( \
VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); \
} \
WRITE_VCBUS_REG(AFBC_ENABLE, 0);\
if (debug_flag & DEBUG_FLAG_BLACKOUT) { \
pr_info("DisableVideoLayer_NoDelay()\n"); \
} \
} while (0)
#define DisableVideoLayer2() \
do { \
CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \
VPP_VD2_POSTBLEND | VPP_VD2_PREBLEND); \
VIDEO_LAYER2_OFF(); \
VD2_MEM_POWER_OFF(); \
} while (0)
#define DisableVideoLayer_PREBELEND() \
do { CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \
VPP_VD1_PREBLEND | VPP_VD2_PREBLEND); \
WRITE_VCBUS_REG(AFBC_ENABLE, 0);\
if (debug_flag & DEBUG_FLAG_BLACKOUT) { \
pr_info("DisableVideoLayer_PREBELEND()\n"); \
} \
} while (0)
/*********************************************************/
#if DEBUG_TMP
static struct switch_dev video1_state_sdev = {
/* android video layer switch device */
.name = "video_layer1",
};
#endif
static DEFINE_MUTEX(video_layer_mutex);
static u32 layer_cap;
static struct disp_info_s glayer_info[MAX_VD_LAYERS];
static struct vframe_pic_mode_s gPic_info[MAX_VD_LAYERS];
static u32 reference_zorder = 128;
/* default value 20 30 */
static s32 black_threshold_width = 20;
static s32 black_threshold_height = 30;
#define MAX_ZOOM_RATIO 300
#define VPP_PREBLEND_VD_V_END_LIMIT 2304
#define DUR2PTS(x) ((x) - ((x) >> 4))
#define DUR2PTS_RM(x) ((x) & 0xf)
#define PTS2DUR(x) (((x) << 4) / 15)
#ifdef VIDEO_PTS_CHASE
static int vpts_chase;
static int av_sync_flag;
static int vpts_chase_counter;
static int vpts_chase_pts_diff;
#endif
static int step_enable;
static int step_flag;
/*seek values on.video_define.h*/
static int debug_flag;
int get_video_debug_flags(void)
{
return debug_flag;
}
/* DEBUG_FLAG_BLACKOUT; */
static int vsync_enter_line_max;
static int vsync_exit_line_max;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
static int vsync_rdma_line_max;
#endif
static u32 framepacking_support __nosavedata;
static unsigned int framepacking_width = 1920;
static unsigned int framepacking_height = 2205;
static unsigned int framepacking_blank = 45;
static unsigned int process_3d_type;
static unsigned int last_process_3d_type;
#ifdef TV_3D_FUNCTION_OPEN
/* toggle_3d_fa_frame is for checking the vpts_expire in 2 vsnyc */
static int toggle_3d_fa_frame = 1;
/*the pause_one_3d_fl_frame is for close*/
/*the A/B register switch in every sync at pause mode. */
static int pause_one_3d_fl_frame;
MODULE_PARM_DESC(pause_one_3d_fl_frame, "\n pause_one_3d_fl_frame\n");
module_param(pause_one_3d_fl_frame, uint, 0664);
/*debug info control for skip & repeate vframe case*/
static unsigned int video_dbg_vf;
MODULE_PARM_DESC(video_dbg_vf, "\n video_dbg_vf\n");
module_param(video_dbg_vf, uint, 0664);
static unsigned int video_get_vf_cnt;
static unsigned int video_drop_vf_cnt;
MODULE_PARM_DESC(video_drop_vf_cnt, "\n video_drop_vf_cnt\n");
module_param(video_drop_vf_cnt, uint, 0664);
static unsigned int video_repeat_vf_cnt;
MODULE_PARM_DESC(video_repeat_vf_cnt, "\n Video frame repeat count\n");
module_param(video_repeat_vf_cnt, uint, 0644);
enum toggle_out_fl_frame_e {
OUT_FA_A_FRAME,
OUT_FA_BANK_FRAME,
OUT_FA_B_FRAME
};
static unsigned int video_3d_format;
static unsigned int mvc_flag;
static unsigned int force_3d_scaler = 3;
static int mode_3d_changed;
static int last_mode_3d;
static int frame_render_ready;
#endif
#ifdef TV_REVERSE
bool reverse;
#endif
const char video_dev_id[] = "amvideo-dev";
const char video_dev_id2[] = "amvideo-dev2";
int onwaitendframe;
static u32 vpp_hold_line = 8;
static u32 stop_update;
struct video_dev_s video_dev[2] = {
{0x1d00 - 0x1d00, 0x1a50 - 0x1a50},
{0x1900 - 0x1d00, 0x1e00 - 0x1a50}
};
struct video_dev_s *cur_dev = &video_dev[0];
struct video_dev_s *get_video_cur_dev(void)
{
return cur_dev;
}
static int cur_dev_idx;
#ifdef CONFIG_PM
struct video_pm_state_s {
int event;
u32 vpp_misc;
int mem_pd_vd1;
int mem_pd_vd2;
int mem_pd_di_post;
};
#endif
#define PTS_LOGGING
#define PTS_THROTTLE
/* #define PTS_TRACE_DEBUG */
/* #define PTS_TRACE_START */
#ifdef PTS_TRACE_DEBUG
static int pts_trace_his[16];
static u32 pts_his[16];
static u32 scr_his[16];
static int pts_trace_his_rd;
#endif
#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG)
static int pts_trace;
#endif
#if defined(PTS_LOGGING)
#define PTS_32_PATTERN_DETECT_RANGE 10
#define PTS_22_PATTERN_DETECT_RANGE 10
#define PTS_41_PATTERN_DETECT_RANGE 2
#define PTS_32_PATTERN_DURATION 3750
#define PTS_22_PATTERN_DURATION 3000
enum video_refresh_pattern {
PTS_32_PATTERN = 0,
PTS_22_PATTERN,
PTS_41_PATTERN,
PTS_MAX_NUM_PATTERNS
};
int n_patterns = PTS_MAX_NUM_PATTERNS;
static int pts_pattern[3] = {0, 0, 0};
static int pts_pattern_enter_cnt[3] = {0, 0, 0};
static int pts_pattern_exit_cnt[3] = {0, 0, 0};
static int pts_log_enable[3] = {0, 0, 0};
static int pre_pts_trace;
static int pts_escape_vsync = -1;
#define PTS_41_PATTERN_SINK_MAX 4
static int pts_41_pattern_sink[PTS_41_PATTERN_SINK_MAX];
static int pts_41_pattern_sink_index;
static int pts_pattern_detected = -1;
static bool pts_enforce_pulldown = true;
#endif
static DEFINE_MUTEX(video_module_mutex);
static DEFINE_MUTEX(video_inuse_mutex);
static DEFINE_SPINLOCK(lock);
#if ENABLE_UPDATE_HDR_FROM_USER
static DEFINE_SPINLOCK(omx_hdr_lock);
#endif
static u32 frame_par_ready_to_set, frame_par_force_to_set;
static u32 vpts_remainder;
static int video_property_changed;
static u32 video_notify_flag;
static int enable_video_discontinue_report = 1;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
static u32 video_scaler_mode;
static int content_top = 0, content_left = 0, content_w = 0, content_h;
static int scaler_pos_changed;
#endif
#ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
bool is_dolby_vision_enable(void)
{
return 0;
}
bool is_dolby_vision_on(void)
{
return 0;
}
bool is_dolby_vision_stb_mode(void)
{
return 0;
}
#endif
static struct amvideocap_req *capture_frame_req;
u32 get_video_angle(void)
{
return glayer_info[0].angle;
}
EXPORT_SYMBOL(get_video_angle);
/*for video related files only.*/
void video_module_lock(void)
{
mutex_lock(&video_module_mutex);
}
void video_module_unlock(void)
{
mutex_unlock(&video_module_mutex);
}
int video_property_notify(int flag)
{
video_property_changed = flag;
return 0;
}
#if defined(PTS_LOGGING)
static ssize_t pts_pattern_enter_cnt_read_file(struct file *file,
char __user *userbuf, size_t count, loff_t *ppos)
{
char buf[20];
ssize_t len;
len = snprintf(buf, 20, "%d,%d,%d\n", pts_pattern_enter_cnt[0],
pts_pattern_enter_cnt[1], pts_pattern_enter_cnt[2]);
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
static ssize_t pts_pattern_exit_cnt_read_file(struct file *file,
char __user *userbuf, size_t count, loff_t *ppos)
{
char buf[20];
ssize_t len;
len = snprintf(buf, 20, "%d,%d,%d\n", pts_pattern_exit_cnt[0],
pts_pattern_exit_cnt[1], pts_pattern_exit_cnt[2]);
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
static ssize_t pts_log_enable_read_file(struct file *file,
char __user *userbuf, size_t count, loff_t *ppos)
{
char buf[20];
ssize_t len;
len = snprintf(buf, 20, "%d,%d,%d\n", pts_log_enable[0],
pts_log_enable[1], pts_log_enable[2]);
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
static ssize_t pts_log_enable_write_file(struct file *file,
const char __user *userbuf, size_t count, loff_t *ppos)
{
char buf[20];
int ret;
count = min_t(size_t, count, (sizeof(buf)-1));
if (copy_from_user(buf, userbuf, count))
return -EFAULT;
buf[count] = 0;
/* pts_pattern_log_enable (3:2) (2:2) (4:1) */
ret = sscanf(buf, "%d,%d,%d", &pts_log_enable[0], &pts_log_enable[1],
&pts_log_enable[2]);
if (ret != 3) {
pr_info("use echo 0/1,0/1,0/1 > /sys/kernel/debug/pts_log_enable\n");
} else {
pr_info("pts_log_enable: %d,%d,%d\n", pts_log_enable[0],
pts_log_enable[1], pts_log_enable[2]);
}
return count;
}
static ssize_t pts_enforce_pulldown_read_file(struct file *file,
char __user *userbuf, size_t count, loff_t *ppos)
{
char buf[16];
ssize_t len;
len = snprintf(buf, 16, "%d\n", pts_enforce_pulldown);
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
static ssize_t pts_enforce_pulldown_write_file(struct file *file,
const char __user *userbuf, size_t count, loff_t *ppos)
{
unsigned int write_val;
char buf[16];
int ret;
count = min_t(size_t, count, (sizeof(buf)-1));
if (copy_from_user(buf, userbuf, count))
return -EFAULT;
buf[count] = 0;
ret = kstrtoint(buf, 0, &write_val);
if (ret != 0)
return -EINVAL;
pr_info("pts_enforce_pulldown: %d->%d\n",
pts_enforce_pulldown, write_val);
pts_enforce_pulldown = write_val;
return count;
}
static const struct file_operations pts_pattern_enter_cnt_file_ops = {
.open = simple_open,
.read = pts_pattern_enter_cnt_read_file,
};
static const struct file_operations pts_pattern_exit_cnt_file_ops = {
.open = simple_open,
.read = pts_pattern_exit_cnt_read_file,
};
static const struct file_operations pts_log_enable_file_ops = {
.open = simple_open,
.read = pts_log_enable_read_file,
.write = pts_log_enable_write_file,
};
static const struct file_operations pts_enforce_pulldown_file_ops = {
.open = simple_open,
.read = pts_enforce_pulldown_read_file,
.write = pts_enforce_pulldown_write_file,
};
#endif
struct video_debugfs_files_s {
const char *name;
const umode_t mode;
const struct file_operations *fops;
};
static struct video_debugfs_files_s video_debugfs_files[] = {
#if defined(PTS_LOGGING)
{"pts_pattern_enter_cnt", S_IFREG | 0444,
&pts_pattern_enter_cnt_file_ops
},
{"pts_pattern_exit_cnt", S_IFREG | 0444,
&pts_pattern_exit_cnt_file_ops
},
{"pts_log_enable", S_IFREG | 0644,
&pts_log_enable_file_ops
},
{"pts_enforce_pulldown", S_IFREG | 0644,
&pts_enforce_pulldown_file_ops
},
#endif
};
static struct dentry *video_debugfs_root;
static void video_debugfs_init(void)
{
struct dentry *ent;
int i;
if (video_debugfs_root)
return;
video_debugfs_root = debugfs_create_dir("video", NULL);
if (!video_debugfs_root)
pr_err("can't create video debugfs dir\n");
for (i = 0; i < ARRAY_SIZE(video_debugfs_files); i++) {
ent = debugfs_create_file(video_debugfs_files[i].name,
video_debugfs_files[i].mode,
video_debugfs_root, NULL,
video_debugfs_files[i].fops);
if (!ent)
pr_info("debugfs create file %s failed\n",
video_debugfs_files[i].name);
}
}
static void video_debugfs_exit(void)
{
debugfs_remove(video_debugfs_root);
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
int video_scaler_notify(int flag)
{
video_scaler_mode = flag;
video_property_changed = 1;
return 0;
}
u32 amvideo_get_scaler_para(int *x, int *y, int *w, int *h, u32 *ratio)
{
*x = content_left;
*y = content_top;
*w = content_w;
*h = content_h;
/* *ratio = 100; */
return video_scaler_mode;
}
void amvideo_set_scaler_para(int x, int y, int w, int h, int flag)
{
struct disp_info_s *layer = &glayer_info[0];
mutex_lock(&video_module_mutex);
if (w < 2)
w = 0;
if (h < 2)
h = 0;
if (flag) {
if ((content_left != x) || (content_top != y)
|| (content_w != w) || (content_h != h))
scaler_pos_changed = 1;
content_left = x;
content_top = y;
content_w = w;
content_h = h;
} else {
layer->layer_left = x;
layer->layer_top = y;
layer->layer_width = w;
layer->layer_height = h;
}
video_property_changed = 1;
mutex_unlock(&video_module_mutex);
}
u32 amvideo_get_scaler_mode(void)
{
return video_scaler_mode;
}
#endif
bool to_notify_trick_wait;
/* display canvas */
#define DISPLAY_CANVAS_BASE_INDEX 0x60
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
static struct vframe_s *cur_rdma_buf;
/*
*void vsync_rdma_config(void);
*void vsync_rdma_config_pre(void);
*bool is_vsync_rdma_enable(void);
*void start_rdma(void);
*void enable_rdma_log(int flag);
*/
static int enable_rdma_log_count;
bool rdma_enable_pre;
u32 disp_canvas_index[2][6] = {
{
DISPLAY_CANVAS_BASE_INDEX,
DISPLAY_CANVAS_BASE_INDEX + 1,
DISPLAY_CANVAS_BASE_INDEX + 2,
DISPLAY_CANVAS_BASE_INDEX + 3,
DISPLAY_CANVAS_BASE_INDEX + 4,
DISPLAY_CANVAS_BASE_INDEX + 5,
},
{
DISPLAY_CANVAS_BASE_INDEX2,
DISPLAY_CANVAS_BASE_INDEX2 + 1,
DISPLAY_CANVAS_BASE_INDEX2 + 2,
DISPLAY_CANVAS_BASE_INDEX2 + 3,
DISPLAY_CANVAS_BASE_INDEX2 + 4,
DISPLAY_CANVAS_BASE_INDEX2 + 5,
}
};
static u32 disp_canvas[2][2];
static u32 rdma_canvas_id;
static u32 next_rdma_canvas_id = 1;
#ifdef VIDEO_PIP
static u32 pip_rdma_canvas_id;
static u32 pip_next_rdma_canvas_id = 1;
static struct vframe_s *pip_rdma_buf;
static struct vframe_s *pipbuf_to_put;
#endif
#define DISPBUF_TO_PUT_MAX 8
static struct vframe_s *dispbuf_to_put[DISPBUF_TO_PUT_MAX];
static int dispbuf_to_put_num;
#else
static u32 disp_canvas_index[6] = {
DISPLAY_CANVAS_BASE_INDEX,
DISPLAY_CANVAS_BASE_INDEX + 1,
DISPLAY_CANVAS_BASE_INDEX + 2,
DISPLAY_CANVAS_BASE_INDEX + 3,
DISPLAY_CANVAS_BASE_INDEX + 4,
DISPLAY_CANVAS_BASE_INDEX + 5,
};
static u32 disp_canvas[2];
#endif
static u32 post_canvas;
/* zoom information */
static u32 zoom_start_x_lines;
static u32 zoom_end_x_lines;
static u32 zoom_start_y_lines;
static u32 zoom_end_y_lines;
static u32 ori_start_x_lines;
static u32 ori_end_x_lines;
static u32 ori_start_y_lines;
static u32 ori_end_y_lines;
static u32 zoom2_start_x_lines;
static u32 zoom2_end_x_lines;
static u32 zoom2_start_y_lines;
static u32 zoom2_end_y_lines;
static u32 ori2_start_x_lines;
static u32 ori2_end_x_lines;
static u32 ori2_start_y_lines;
static u32 ori2_end_y_lines;
/* black out policy */
#if defined(CONFIG_JPEGLOGO)
static u32 blackout;
#else
static u32 blackout = 1;
#endif
static u32 force_blackout;
static u32 blackout_pip;
/* disable video */
#ifdef VIDEO_PIP
static u32 pip_frame_count;
static u32 disable_videopip = VIDEO_DISABLE_FORNEXT;
static int pip_property_changed;
static u32 pip_frame_ready_to_set;
static u32 pip_global_output = 1;
#if 0
static u32 pip_v_skip;
static u32 pip_h_skip;
static u32 pip_start_x_lines;
static u32 pip_end_x_lines;
static u32 pip_start_y_lines;
static u32 pip_end_y_lines;
#endif
static u32 pip_loop;
#endif
static u32 disable_video = VIDEO_DISABLE_NONE;
static u32 video_enabled __nosavedata;
static u32 video2_enabled __nosavedata;
static u32 video_status_saved __nosavedata;
static u32 video2_status_saved __nosavedata;
static u32 hold_video;
u32 get_video_enabled(void)
{
return video_enabled;
}
u32 get_videopip_enabled(void)
{
return video2_enabled;
}
/* show first frame*/
static bool show_first_frame_nosync;
bool show_first_picture;
/* static bool first_frame=false; */
/* test screen*/
static u32 test_screen;
/* rgb screen*/
static u32 rgb_screen;
/* video frame repeat count */
static u32 frame_repeat_count;
/* vout */
static const struct vinfo_s *vinfo;
/* config */
static struct vframe_s *cur_dispbuf;
static struct vframe_s *cur_dispbuf2;
static bool need_disable_vd2;
static bool last_mvc_status;
void update_cur_dispbuf(void *buf)
{
cur_dispbuf = buf;
}
static struct vframe_s vf_local, vf_local2;
static u32 vsync_pts_inc;
static u32 vsync_pts_inc_scale;
static u32 vsync_pts_inc_scale_base = 1;
static u32 vsync_pts_inc_upint;
static u32 vsync_pts_inc_adj;
static u32 vsync_pts_125;
static u32 vsync_pts_112;
static u32 vsync_pts_101;
static u32 vsync_pts_100;
static u32 vsync_freerun;
/* extend this value to support both slow and fast playback
* 0,1: normal playback
* [2,1000]: speed/vsync_slow_factor
* >1000: speed*(vsync_slow_factor/1000000)
*/
static u32 vsync_slow_factor = 1;
/* pts alignment */
static bool vsync_pts_aligned;
static s32 vsync_pts_align;
/* frame rate calculate */
static u32 last_frame_count;
static u32 frame_count;
static u32 new_frame_count;
static u32 first_frame_toggled;
static u32 toggle_count;
static u32 last_frame_time;
static u32 timer_count;
static u32 vsync_count;
static u64 last_frame_duration;
static struct vpp_frame_par_s *cur_frame_par, *next_frame_par;
static struct vpp_frame_par_s frame_parms[2];
/* vsync pass flag */
static u32 wait_sync;
/* is fffb or seeking*/
static u32 video_seek_flag;
#ifdef FIQ_VSYNC
static bridge_item_t vsync_fiq_bridge;
#endif
/* trickmode i frame*/
u32 trickmode_i;
EXPORT_SYMBOL(trickmode_i);
/* trickmode ff/fb */
u32 trickmode_fffb;
atomic_t trickmode_framedone = ATOMIC_INIT(0);
atomic_t video_sizechange = ATOMIC_INIT(0);
atomic_t video_unreg_flag = ATOMIC_INIT(0);
atomic_t video_inirq_flag = ATOMIC_INIT(0);
atomic_t video_pause_flag = ATOMIC_INIT(0);
int trickmode_duration;
int trickmode_duration_count;
u32 trickmode_vpts;
/* last_playback_filename */
char file_name[512];
/* video freerun mode */
#define FREERUN_NONE 0 /* no freerun mode */
#define FREERUN_NODUR 1 /* freerun without duration */
#define FREERUN_DUR 2 /* freerun with duration */
static u32 freerun_mode;
static u32 slowsync_repeat_enable;
static bool dmc_adjust = true;
module_param_named(dmc_adjust, dmc_adjust, bool, 0644);
static u32 dmc_config_state;
static u32 last_toggle_count;
static u32 toggle_same_count;
/* video_inuse */
static u32 video_inuse;
void set_freerun_mode(int mode)
{
freerun_mode = mode;
}
EXPORT_SYMBOL(set_freerun_mode);
void set_pts_realign(void)
{
vsync_pts_aligned = false;
}
EXPORT_SYMBOL(set_pts_realign);
static const enum f2v_vphase_type_e vpp_phase_table[4][3] = {
{F2V_P2IT, F2V_P2IB, F2V_P2P}, /* VIDTYPE_PROGRESSIVE */
{F2V_IT2IT, F2V_IT2IB, F2V_IT2P}, /* VIDTYPE_INTERLACE_TOP */
{F2V_P2IT, F2V_P2IB, F2V_P2P},
{F2V_IB2IT, F2V_IB2IB, F2V_IB2P} /* VIDTYPE_INTERLACE_BOTTOM */
};
static const u8 skip_tab[6] = { 0x24, 0x04, 0x68, 0x48, 0x28, 0x08 };
/* wait queue for poll */
static wait_queue_head_t amvideo_trick_wait;
/* wait queue for poll */
static wait_queue_head_t amvideo_event_wait;
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
#define VPU_DELAYWORK_VPU_CLK 1
#define VPU_DELAYWORK_MEM_POWER_OFF_VD1 2
#define VPU_DELAYWORK_MEM_POWER_OFF_VD2 4
#define VPU_DELAYWORK_MEM_POWER_OFF_PROT 8
#define VPU_VIDEO_LAYER1_CHANGED 16
#define VPU_UPDATE_DOLBY_VISION 32
#define VPU_MEM_POWEROFF_DELAY 100
static struct work_struct vpu_delay_work;
static int vpu_clk_level;
static DEFINE_SPINLOCK(delay_work_lock);
static int vpu_delay_work_flag;
static int vpu_mem_power_off_count;
#endif
static u32 vpts_ref;
static u32 video_frame_repeat_count;
static u32 smooth_sync_enable;
static u32 hdmi_in_onvideo;
#ifdef CONFIG_AM_VIDEO2
static int video_play_clone_rate = 60;
static int android_clone_rate = 30;
static int noneseamless_play_clone_rate = 5;
#endif
#define CONFIG_AM_VOUT
void safe_disble_videolayer(void)
{
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (video_scaler_mode)
DisableVideoLayer_PREBELEND();
else
DisableVideoLayer();
#else
DisableVideoLayer();
#endif
}
#ifdef VIDEO_PIP
void safe_disble_videolayer2(void)
{
DisableVideoLayer2();
}
#endif
/*********************************************************/
#ifdef VIDEO_PIP
static inline struct vframe_s *pip_vf_peek(void)
{
if (pip_loop)
return cur_dispbuf;
return vf_peek(RECEIVERPIP_NAME);
}
static inline struct vframe_s *pip_vf_get(void)
{
struct vframe_s *vf = NULL;
if (pip_loop)
return cur_dispbuf;
vf = vf_get(RECEIVERPIP_NAME);
if (vf) {
/* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */
atomic_set(&vf->use_cnt, 1);
}
return vf;
}
#if 0
static int pip_vf_get_states(struct vframe_states *states)
{
int ret = -1;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
ret = vf_get_states_by_name(RECEIVERPIP_NAME, states);
spin_unlock_irqrestore(&lock, flags);
return ret;
}
#endif
static inline void pip_vf_put(struct vframe_s *vf)
{
struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP_NAME);
if (pip_loop)
return;
if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) {
vf_put(vf, RECEIVERPIP_NAME);
/* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */
}
}
#endif
static inline struct vframe_s *video_vf_peek(void)
{
struct vframe_s *vf = vf_peek(RECEIVER_NAME);
if (vf && vf->disp_pts && vf->disp_pts_us64) {
vf->pts = vf->disp_pts;
vf->pts_us64 = vf->disp_pts_us64;
vf->disp_pts = 0;
vf->disp_pts_us64 = 0;
}
return vf;
}
static inline struct vframe_s *video_vf_get(void)
{
struct vframe_s *vf = NULL;
int frame_width, frame_height;
vf = vf_get(RECEIVER_NAME);
if (vf) {
if (vf->disp_pts && vf->disp_pts_us64) {
vf->pts = vf->disp_pts;
vf->pts_us64 = vf->disp_pts_us64;
vf->disp_pts = 0;
vf->disp_pts_us64 = 0;
}
if (vf->type & VIDTYPE_COMPRESS) {
frame_width = vf->compWidth;
frame_height = vf->compHeight;
} else {
frame_width = vf->width;
frame_height = vf->height;
}
video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET;
atomic_set(&vf->use_cnt, 1);
/*always to 1,for first get from vfm provider */
if ((vf->type & VIDTYPE_MVC) && (framepacking_support)
&&(framepacking_width) && (framepacking_height)) {
vf->width = framepacking_width;
vf->height = framepacking_height;
}
#ifdef TV_3D_FUNCTION_OPEN
/*can be moved to h264mvc.c */
if ((vf->type & VIDTYPE_MVC)
&& (process_3d_type & MODE_3D_ENABLE) && vf->trans_fmt) {
vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
process_3d_type |= MODE_3D_MVC;
mvc_flag = 1;
} else {
process_3d_type &= (~MODE_3D_MVC);
mvc_flag = 0;
}
if (((process_3d_type & MODE_FORCE_3D_TO_2D_LR)
|| (process_3d_type & MODE_FORCE_3D_LR)
|| (process_3d_type & MODE_FORCE_3D_FA_LR))
&& (!(vf->type & VIDTYPE_MVC))
&& (vf->trans_fmt != TVIN_TFMT_3D_FP)) {
vf->trans_fmt = TVIN_TFMT_3D_DET_LR;
vf->left_eye.start_x = 0;
vf->left_eye.start_y = 0;
vf->left_eye.width = frame_width / 2;
vf->left_eye.height = frame_height;
vf->right_eye.start_x = frame_width / 2;
vf->right_eye.start_y = 0;
vf->right_eye.width = frame_width / 2;
vf->right_eye.height = frame_height;
}
if (((process_3d_type & MODE_FORCE_3D_TO_2D_TB)
|| (process_3d_type & MODE_FORCE_3D_TB)
|| (process_3d_type & MODE_FORCE_3D_FA_TB))
&& (!(vf->type & VIDTYPE_MVC))
&& (vf->trans_fmt != TVIN_TFMT_3D_FP)) {
vf->trans_fmt = TVIN_TFMT_3D_TB;
vf->left_eye.start_x = 0;
vf->left_eye.start_y = 0;
vf->left_eye.width = frame_width;
vf->left_eye.height = frame_height/2;
vf->right_eye.start_x = 0;
vf->right_eye.start_y = frame_height/2;
vf->right_eye.width = frame_width;
vf->right_eye.height = frame_height/2;
}
receive_frame_count++;
#endif
}
return vf;
}
static int video_vf_get_states(struct vframe_states *states)
{
int ret = -1;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
ret = vf_get_states_by_name(RECEIVER_NAME, states);
spin_unlock_irqrestore(&lock, flags);
return ret;
}
static inline void video_vf_put(struct vframe_s *vf)
{
struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME);
if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) {
vf_put(vf, RECEIVER_NAME);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable())
dolby_vision_vf_put(vf);
#endif
video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT;
}
}
int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index)
{
if (cur_dispbuf == NULL)
return -1;
atomic_inc(&cur_dispbuf->use_cnt);
*canvas_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off);
*vf = cur_dispbuf;
return 0;
}
static void dump_vframe_status(const char *name)
{
int ret = -1;
struct vframe_states states;
struct vframe_provider_s *vfp;
vfp = vf_get_provider_by_name(name);
if (vfp && vfp->ops && vfp->ops->vf_states)
ret = vfp->ops->vf_states(&states, vfp->op_arg);
if (ret == 0) {
ret += pr_info("%s_pool_size=%d\n",
name, states.vf_pool_size);
ret += pr_info("%s buf_free_num=%d\n",
name, states.buf_free_num);
ret += pr_info("%s buf_avail_num=%d\n",
name, states.buf_avail_num);
} else {
ret += pr_info("%s vframe no states\n", name);
}
}
static void dump_vdin_reg(void)
{
unsigned int reg001, reg002;
reg001 = READ_VCBUS_REG(0x1204);
reg002 = READ_VCBUS_REG(0x1205);
pr_info("VDIN_LCNT_STATUS:0x%x,VDIN_COM_STATUS0:0x%x\n",
reg001, reg002);
}
#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE
int ext_put_video_frame(struct vframe_s *vf)
{
if (vf == &vf_local)
return 0;
video_vf_put(vf);
return 0;
}
static int is_need_framepacking_output(void)
{
int ret = 0;
if ((framepacking_support) &&
(cur_dispbuf) && (cur_dispbuf->type & VIDTYPE_MVC)) {
ret = 1;
}
return ret;
}
int ext_register_end_frame_callback(struct amvideocap_req *req)
{
mutex_lock(&video_module_mutex);
capture_frame_req = req;
mutex_unlock(&video_module_mutex);
return 0;
}
int ext_frame_capture_poll(int endflags)
{
mutex_lock(&video_module_mutex);
if (capture_frame_req && capture_frame_req->callback) {
struct vframe_s *vf;
int index;
int ret;
struct amvideocap_req *req = capture_frame_req;
ret = ext_get_cur_video_frame(&vf, &index);
if (!ret) {
req->callback(req->data, vf, index);
capture_frame_req = NULL;
}
}
mutex_unlock(&video_module_mutex);
return 0;
}
#endif
static void update_layer_info(u8 layer_id)
{
struct disp_info_s *layer;
if (layer_id >= MAX_VD_LAYERS)
return;
if (layer_id == 0) {
layer = &glayer_info[0];
layer->reverse = reverse;
layer->proc_3d_type = process_3d_type;
} else if (layer_id == 1) {
layer = &glayer_info[1];
layer->reverse = reverse;
layer->proc_3d_type = 0;
}
}
static void vpp_settings_h(struct vpp_frame_par_s *framePtr)
{
struct vppfilter_mode_s *vpp_filter = &framePtr->vpp_filter;
u32 r1, r2, r3;
u32 x_lines;
r1 = framePtr->VPP_hsc_linear_startp - framePtr->VPP_hsc_startp;
r2 = framePtr->VPP_hsc_linear_endp - framePtr->VPP_hsc_startp;
r3 = framePtr->VPP_hsc_endp - framePtr->VPP_hsc_startp;
if ((framePtr->supscl_path == CORE0_PPS_CORE1) ||
(framePtr->supscl_path == CORE1_AFTER_PPS) ||
(framePtr->supscl_path == PPS_CORE0_CORE1) ||
(framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1))
r3 >>= framePtr->supsc1_hori_ratio;
if ((framePtr->supscl_path == CORE0_AFTER_PPS) ||
(framePtr->supscl_path == PPS_CORE0_CORE1) ||
(framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1))
r3 >>= framePtr->supsc0_hori_ratio;
x_lines = zoom_end_x_lines / (framePtr->hscale_skip_count + 1);
if (process_3d_type & MODE_3D_OUT_TB) {
/* vd1 and vd2 do pre blend */
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END,
((zoom_start_x_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | (((zoom_end_x_lines) &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END,
((zoom_start_x_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | (((zoom_end_x_lines) &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END +
cur_dev->vpp_off,
((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK)
<< VPP_VD1_START_BIT) |
((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
} else if (process_3d_type & MODE_3D_OUT_LR) {
/* vd1 and vd2 do pre blend */
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END,
((zoom_start_x_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | (((x_lines >> 1) &
VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END,
((((x_lines + 1) >> 1) & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | ((x_lines &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END +
cur_dev->vpp_off,
((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK)
<< VPP_VD1_START_BIT) |
((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
} else{
if (!legacy_vpp) {
x_lines = (zoom_end_x_lines -
zoom_start_x_lines + 1)
/ (framePtr->hscale_skip_count + 1);
VSYNC_WR_MPEG_REG(
VPP_PREBLEND_VD1_H_START_END,
((0 & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | (((x_lines - 1) &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
}
VSYNC_WR_MPEG_REG(
VPP_POSTBLEND_VD1_H_START_END +
cur_dev->vpp_off,
((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK)
<< VPP_VD1_START_BIT) |
((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
#ifdef VIDEO_PIP
if (!cur_pipbuf)
#endif
{
VSYNC_WR_MPEG_REG(
VPP_BLEND_VD2_H_START_END +
cur_dev->vpp_off,
((framePtr->VPP_hd_start_lines_ &
VPP_VD_SIZE_MASK)
<< VPP_VD1_START_BIT) |
((framePtr->VPP_hd_end_lines_ &
VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
}
}
VSYNC_WR_MPEG_REG(VPP_HSC_REGION12_STARTP +
cur_dev->vpp_off,
(0 << VPP_REGION1_BIT) |
((r1 & VPP_REGION_MASK) << VPP_REGION2_BIT));
VSYNC_WR_MPEG_REG(VPP_HSC_REGION34_STARTP + cur_dev->vpp_off,
((r2 & VPP_REGION_MASK) << VPP_REGION3_BIT) |
((r3 & VPP_REGION_MASK) << VPP_REGION4_BIT));
VSYNC_WR_MPEG_REG(VPP_HSC_REGION4_ENDP + cur_dev->vpp_off, r3);
VSYNC_WR_MPEG_REG(VPP_HSC_START_PHASE_STEP + cur_dev->vpp_off,
vpp_filter->vpp_hf_start_phase_step);
VSYNC_WR_MPEG_REG(VPP_HSC_REGION1_PHASE_SLOPE + cur_dev->vpp_off,
vpp_filter->vpp_hf_start_phase_slope);
VSYNC_WR_MPEG_REG(VPP_HSC_REGION3_PHASE_SLOPE + cur_dev->vpp_off,
vpp_filter->vpp_hf_end_phase_slope);
VSYNC_WR_MPEG_REG(VPP_LINE_IN_LENGTH + cur_dev->vpp_off,
framePtr->VPP_line_in_length_);
}
static void vd2_settings_h(struct vframe_s *vf)
{
u32 VPP_hd_start_lines_;
u32 VPP_hd_end_lines_;
if (vf) {
VPP_hd_start_lines_ = 0;
VPP_hd_end_lines_ = ((vf->type & VIDTYPE_COMPRESS) ?
vf->compWidth : vf->width) - 1;
VSYNC_WR_MPEG_REG(
VPP_BLEND_VD2_H_START_END +
cur_dev->vpp_off,
((VPP_hd_start_lines_ &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
((VPP_hd_end_lines_ &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
}
}
static void vpp_settings_v(struct vpp_frame_par_s *framePtr)
{
struct vppfilter_mode_s *vpp_filter = &framePtr->vpp_filter;
u32 r, afbc_enble_flag;
u32 y_lines;
u32 v_phase;
u32 v_skip_flag = 0;
int x, y, w, h;
struct disp_info_s *layer = &glayer_info[0];
r = framePtr->VPP_vsc_endp - framePtr->VPP_vsc_startp;
afbc_enble_flag = 0;
if (is_meson_gxbb_cpu())
afbc_enble_flag = READ_VCBUS_REG(AFBC_ENABLE) & 0x100;
if ((vpp_filter->vpp_vsc_start_phase_step > 0x1000000)
&& afbc_enble_flag)
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END +
cur_dev->vpp_off, ((framePtr->VPP_vsc_startp &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT)
| (((framePtr->VPP_vsc_endp + 1) & VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
else {
afbc_enble_flag = READ_VCBUS_REG(AFBC_ENABLE) & 0x100;
v_phase = vpp_filter->vpp_vsc_start_phase_step;
x = layer->layer_left;
y = layer->layer_top;
w = layer->layer_width;
h = layer->layer_height;
if (v_phase * (framePtr->vscale_skip_count + 1) > 0x1000000) {
if ((afbc_enble_flag) && (y < 0)) {
if ((framePtr->VPP_vsc_endp < 0x250) ||
(framePtr->VPP_vsc_endp <
framePtr->VPP_post_blend_vd_v_end_/2)) {
if (framePtr->VPP_vsc_endp > 0x6)
v_skip_flag = 1;
}
}
}
if (v_skip_flag == 1) {
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END +
cur_dev->vpp_off, ((framePtr->VPP_vsc_startp &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT)
| (((framePtr->VPP_vsc_endp - 6) & VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
} else {
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END +
cur_dev->vpp_off, ((framePtr->VPP_vsc_startp &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT)
| ((framePtr->VPP_vsc_endp & VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
}
}
y_lines = zoom_end_y_lines / (framePtr->vscale_skip_count + 1);
if (process_3d_type & MODE_3D_OUT_TB) {
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END,
((zoom_start_y_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | (((y_lines >> 1) &
VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(
VPP_BLEND_VD2_V_START_END,
((((y_lines + 1) >> 1) & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) |
((y_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
} else if (process_3d_type & MODE_3D_OUT_LR) {
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END,
((zoom_start_y_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | ((zoom_end_y_lines &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END,
((zoom_start_y_lines & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | ((zoom_end_y_lines &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
} else {
if ((framePtr->VPP_post_blend_vd_v_end_ -
framePtr->VPP_post_blend_vd_v_start_ + 1) >
VPP_PREBLEND_VD_V_END_LIMIT) {
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END +
cur_dev->vpp_off,
((framePtr->VPP_post_blend_vd_v_start_
& VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) |
((framePtr->VPP_post_blend_vd_v_end_ &
VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
} else {
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END +
cur_dev->vpp_off,
((0 & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) |
(((VPP_PREBLEND_VD_V_END_LIMIT - 1) &
VPP_VD_SIZE_MASK) <<
VPP_VD1_END_BIT));
}
#ifdef VIDEO_PIP
if (!cur_pipbuf)
#endif
{
VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END +
cur_dev->vpp_off,
((((framePtr->VPP_vd_end_lines_ + 1) / 2) &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
(((framePtr->VPP_vd_end_lines_) &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
}
if (is_need_framepacking_output()) {
VSYNC_WR_MPEG_REG(
VPP_BLEND_VD2_V_START_END +
cur_dev->vpp_off,
(((((framePtr->VPP_vd_end_lines_ -
framepacking_blank + 1) / 2) + framepacking_blank) &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
(((framePtr->VPP_vd_end_lines_) &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
}
}
VSYNC_WR_MPEG_REG(VPP_VSC_REGION12_STARTP + cur_dev->vpp_off, 0);
VSYNC_WR_MPEG_REG(VPP_VSC_REGION34_STARTP + cur_dev->vpp_off,
((r & VPP_REGION_MASK) << VPP_REGION3_BIT) |
((r & VPP_REGION_MASK) << VPP_REGION4_BIT));
if ((framePtr->supscl_path == CORE0_PPS_CORE1) ||
(framePtr->supscl_path == CORE1_AFTER_PPS) ||
(framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1))
r >>= framePtr->supsc1_vert_ratio;
if ((framePtr->supscl_path == CORE0_AFTER_PPS) ||
(framePtr->supscl_path == PPS_CORE0_CORE1) ||
(framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1))
r >>= framePtr->supsc0_vert_ratio;
VSYNC_WR_MPEG_REG(VPP_VSC_REGION4_ENDP + cur_dev->vpp_off, r);
VSYNC_WR_MPEG_REG(VPP_VSC_START_PHASE_STEP + cur_dev->vpp_off,
vpp_filter->vpp_vsc_start_phase_step);
}
static void vd2_settings_v(struct vframe_s *vf)
{
u32 VPP_vd_start_lines_;
u32 VPP_vd_end_lines_;
if (vf) {
VPP_vd_start_lines_ = 0;
VPP_vd_end_lines_ = ((vf->type & VIDTYPE_COMPRESS) ?
vf->compHeight : vf->height) - 1;
VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END +
cur_dev->vpp_off,
((VPP_vd_start_lines_ &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
(((VPP_vd_end_lines_) &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
}
}
#ifdef TV_3D_FUNCTION_OPEN
static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls,
u32 *le, u32 *rs, u32 *re)
{
u32 crop_sx, crop_ex, crop_sy, crop_ey;
int frame_width, frame_height;
struct disp_info_s *layer = &glayer_info[0];
if (!vf)
return;
crop_sy = layer->crop_top;
crop_sx = layer->crop_left;
crop_ey = layer->crop_bottom;
crop_ex = layer->crop_right;
if (vf->type & VIDTYPE_COMPRESS) {
frame_width = vf->compWidth;
frame_height = vf->compHeight;
} else {
frame_width = vf->width;
frame_height = vf->height;
}
switch (vpp_3d_mode) {
case VPP_3D_MODE_LR:
/*half width,double height */
*ls = zoom_start_x_lines;
*le = zoom_end_x_lines;
*rs = *ls + (frame_width >> 1);
*re = *le + (frame_width >> 1);
if (process_3d_type & MODE_3D_OUT_LR) {
*ls = zoom_start_x_lines;
*le = zoom_end_x_lines >> 1;
*rs = *ls + (frame_width >> 1);
*re = *le + (frame_width >> 1);
}
break;
case VPP_3D_MODE_TB:
case VPP_3D_MODE_LA:
case VPP_3D_MODE_FA:
default:
if (vf->trans_fmt == TVIN_TFMT_3D_FP) {
*ls = vf->left_eye.start_x + crop_sx;
*le = vf->left_eye.start_x + vf->left_eye.width -
crop_ex - 1;
*rs = vf->right_eye.start_x + crop_sx;
*re = vf->right_eye.start_x + vf->right_eye.width -
crop_ex - 1;
} else if (process_3d_type & MODE_3D_OUT_LR) {
*ls = zoom_start_x_lines;
*le = zoom_end_x_lines >> 1;
*rs = *ls;
*re = *le;
/* *rs = *ls + (vf->width); */
/* *re = *le + (vf->width); */
} else {
*ls = *rs = zoom_start_x_lines;
*le = *re = zoom_end_x_lines;
}
break;
}
}
static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls,
u32 *le, u32 *rs, u32 *re)
{
u32 crop_sx, crop_ex, crop_sy, crop_ey, height;
int frame_width, frame_height;
struct disp_info_s *layer = &glayer_info[0];
if (!vf)
return;
crop_sy = layer->crop_top;
crop_sx = layer->crop_left;
crop_ey = layer->crop_bottom;
crop_ex = layer->crop_right;
if (vf->type & VIDTYPE_COMPRESS) {
frame_width = vf->compWidth;
frame_height = vf->compHeight;
} else {
frame_width = vf->width;
frame_height = vf->height;
}
if (vf->type & VIDTYPE_INTERLACE)
height = frame_height >> 1;
else
height = frame_height;
switch (vpp_3d_mode) {
case VPP_3D_MODE_TB:
if (vf->trans_fmt == TVIN_TFMT_3D_FP) {
if (vf->type & VIDTYPE_INTERLACE) {
/*if input is interlace vertical*/
/*crop will be reduce by half */
*ls =
(vf->left_eye.start_y +
(crop_sy >> 1)) >> 1;
*le =
((vf->left_eye.start_y +
vf->left_eye.height -
(crop_ey >> 1)) >> 1) - 1;
*rs =
(vf->right_eye.start_y +
(crop_sy >> 1)) >> 1;
*re =
((vf->right_eye.start_y +
vf->left_eye.height -
(crop_ey >> 1)) >> 1) - 1;
} else {
*ls = vf->left_eye.start_y + (crop_sy >> 1);
*le = vf->left_eye.start_y +
vf->left_eye.height -
(crop_ey >> 1) - 1;
*rs = vf->right_eye.start_y + (crop_sy >> 1);
*re =
vf->right_eye.start_y +
vf->left_eye.height - (crop_ey >> 1) - 1;
}
} else {
if ((vf->type & VIDTYPE_VIU_FIELD)
&& (vf->type & VIDTYPE_INTERLACE)) {
*ls = zoom_start_y_lines >> 1;
*le = zoom_end_y_lines >> 1;
*rs = *ls + (height >> 1);
*re = *le + (height >> 1);
} else if (vf->type & VIDTYPE_INTERLACE) {
*ls = zoom_start_y_lines >> 1;
*le = zoom_end_y_lines >> 1;
*rs = *ls + height;
*re = *le + height;
} else {
/* same width,same height */
*ls = zoom_start_y_lines >> 1;
*le = zoom_end_y_lines >> 1;
*rs = *ls + (height >> 1);
*re = *le + (height >> 1);
}
if ((process_3d_type & MODE_3D_TO_2D_MASK)
|| (process_3d_type & MODE_3D_OUT_LR)) {
/* same width,half height */
*ls = zoom_start_y_lines;
*le = zoom_end_y_lines;
*rs = zoom_start_y_lines + (height >> 1);
*re = zoom_end_y_lines + (height >> 1);
}
}
break;
case VPP_3D_MODE_LR:
/* half width,double height */
*ls = *rs = zoom_start_y_lines >> 1;
*le = *re = zoom_end_y_lines >> 1;
if ((process_3d_type & MODE_3D_TO_2D_MASK)
|| (process_3d_type & MODE_3D_OUT_LR)) {
/*half width ,same height */
*ls = *rs = zoom_start_y_lines;
*le = *re = zoom_end_y_lines;
}
break;
case VPP_3D_MODE_FA:
/*same width same heiht */
if ((process_3d_type & MODE_3D_TO_2D_MASK)
|| (process_3d_type & MODE_3D_OUT_LR)) {
*ls = *rs = zoom_start_y_lines;
*le = *re = zoom_end_y_lines;
} else {
*ls = *rs = (zoom_start_y_lines + crop_sy) >> 1;
*le = *re = (zoom_end_y_lines + crop_ey) >> 1;
}
break;
case VPP_3D_MODE_LA:
*ls = *rs = zoom_start_y_lines;
if ((process_3d_type & MODE_3D_LR_SWITCH)
|| (process_3d_type & MODE_3D_TO_2D_R))
*ls = *rs = zoom_start_y_lines + 1;
if (process_3d_type & MODE_3D_TO_2D_L)
*ls = *rs = zoom_start_y_lines;
*le = *re = zoom_end_y_lines;
if ((process_3d_type & MODE_3D_OUT_FA_MASK)
|| (process_3d_type & MODE_3D_OUT_TB)
|| (process_3d_type & MODE_3D_OUT_LR)) {
*rs = zoom_start_y_lines + 1;
*ls = zoom_start_y_lines;
/* *le = zoom_end_y_lines; */
/* *re = zoom_end_y_lines; */
}
break;
default:
*ls = *rs = zoom_start_y_lines;
*le = *re = zoom_end_y_lines;
break;
}
}
#endif
static void zoom_display_horz(struct vframe_s *vf, int hscale)
{
u32 ls = 0, le = 0, rs = 0, re = 0;
#ifdef TV_REVERSE
int content_w, content_l, content_r;
#endif
#ifdef TV_3D_FUNCTION_OPEN
if (process_3d_type & MODE_3D_ENABLE) {
zoom_get_horz_pos(vf, cur_frame_par->vpp_3d_mode, &ls,
&le, &rs, &re);
} else {
ls = rs = zoom_start_x_lines;
le = re = zoom_end_x_lines;
}
#else
ls = rs = zoom_start_x_lines;
le = re = zoom_end_x_lines;
#endif
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_X0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_X0 + cur_dev->viu_off,
(ls / 2 << VDIF_PIC_START_BIT) |
(le / 2 << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_X1 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_X1 + cur_dev->viu_off,
(rs / 2 << VDIF_PIC_START_BIT) |
(re / 2 << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(VIU_VD1_FMT_W + cur_dev->viu_off,
(((zoom_end_x_lines - zoom_start_x_lines +
1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) |
(((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 +
1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
int l_aligned;
int r_aligned;
int h_skip = cur_frame_par->hscale_skip_count + 1;
int c_skip = 2;
/* After TL1, afbc supports 420/422/444*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
if (vf && (vf->type & VIDTYPE_VIU_444))
c_skip = 1;
if ((zoom_start_x_lines > 0) ||
(zoom_end_x_lines < ori_end_x_lines)) {
l_aligned = round_down(ori_start_x_lines, 32);
r_aligned = round_up(ori_end_x_lines + 1, 32);
} else {
l_aligned = round_down(zoom_start_x_lines, 32);
r_aligned = round_up(zoom_end_x_lines + 1, 32);
}
VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_W,
(((r_aligned - l_aligned) / h_skip) << 16) |
((r_aligned / c_skip - l_aligned / c_skip) / h_skip));
VSYNC_WR_MPEG_REG(AFBC_MIF_HOR_SCOPE,
((l_aligned / 32) << 16) |
((r_aligned / 32) - 1));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT,
(VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT)
& 0xffff) |
(((r_aligned - l_aligned) / h_skip) << 16));
}
#ifdef TV_REVERSE
if (reverse) {
content_w = zoom_end_x_lines - zoom_start_x_lines + 1;
content_l = (r_aligned - zoom_end_x_lines - 1);
content_r = content_l + content_w - 1;
VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE,
(((content_l << 16)) | content_r) / h_skip);
} else
#endif
{
if (((process_3d_type & MODE_3D_FA)
|| (process_3d_type & MODE_FORCE_3D_FA_LR))
&& (cur_frame_par->vpp_3d_mode == 1)) {
/* do nothing*/
} else {
VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE,
(((zoom_start_x_lines - l_aligned) << 16) |
(zoom_end_x_lines - l_aligned)) / h_skip);
}
}
VSYNC_WR_MPEG_REG(AFBC_SIZE_IN,
(VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) & 0xffff) |
((r_aligned - l_aligned) << 16));
}
#ifdef VIDEO_PIP
if (!cur_pipbuf)
#endif
{
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_X0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_X0 + cur_dev->viu_off,
(ls / 2 << VDIF_PIC_START_BIT) |
(le / 2 << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_X1 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_X1 + cur_dev->viu_off,
(rs / 2 << VDIF_PIC_START_BIT) |
(re / 2 << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_W + cur_dev->viu_off,
(((zoom_end_x_lines - zoom_start_x_lines +
1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) |
(((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 +
1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT));
}
}
static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale)
{
u32 ls, le, rs, re;
#ifdef TV_REVERSE
int content_w, content_l, content_r;
#endif
ls = rs = zoom2_start_x_lines;
le = re = zoom2_end_x_lines;
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
int l_aligned;
int r_aligned;
int h_skip = hscale + 1;
int c_skip = 2;
/* After TL1, afbc supports 420/422/444*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
if (vf && (vf->type & VIDTYPE_VIU_444))
c_skip = 1;
if ((zoom2_start_x_lines > 0) ||
(zoom2_end_x_lines < ori2_end_x_lines)) {
l_aligned = round_down(ori2_start_x_lines, 32);
r_aligned = round_up(ori2_end_x_lines + 1, 32);
} else {
l_aligned = round_down(zoom2_start_x_lines, 32);
r_aligned = round_up(zoom2_end_x_lines + 1, 32);
}
VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_W,
(((r_aligned - l_aligned) / h_skip) << 16) |
((r_aligned / c_skip - l_aligned / c_skip) / h_skip));
VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_HOR_SCOPE,
((l_aligned / 32) << 16) |
((r_aligned / 32) - 1));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT,
(VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT)
& 0xffff) |
(((r_aligned - l_aligned) / h_skip) << 16));
}
#ifdef TV_REVERSE
if (reverse) {
content_w = zoom2_end_x_lines - zoom2_start_x_lines + 1;
content_l = (r_aligned - zoom2_end_x_lines - 1) +
(zoom2_start_x_lines - l_aligned);
content_r = content_l + content_w - 1;
VSYNC_WR_MPEG_REG(VD2_AFBC_PIXEL_HOR_SCOPE,
(content_l << 16) | content_r);
} else
#endif
{
VSYNC_WR_MPEG_REG(VD2_AFBC_PIXEL_HOR_SCOPE,
((zoom2_start_x_lines - l_aligned) << 16) |
(zoom2_end_x_lines - l_aligned));
}
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_IN,
(VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN) & 0xffff) |
((r_aligned - l_aligned) << 16));
}
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_X0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_X0 + cur_dev->viu_off,
(ls / 2 << VDIF_PIC_START_BIT) |
(le / 2 << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_X1 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_X1 + cur_dev->viu_off,
(rs / 2 << VDIF_PIC_START_BIT) |
(re / 2 << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_W + cur_dev->viu_off,
(((le - ls + 1) >> hscale)
<< VD1_FMT_LUMA_WIDTH_BIT) |
(((le / 2 - ls / 2 + 1) >> hscale)
<< VD1_FMT_CHROMA_WIDTH_BIT));
}
static void zoom_display_vert(struct vframe_s *vf)
{
u32 ls = 0, le = 0, rs = 0, re = 0;
if (process_3d_type & MODE_3D_ENABLE) {
zoom_get_vert_pos(vf,
cur_frame_par->vpp_3d_mode, &ls,
&le, &rs, &re);
} else {
ls = rs = zoom_start_y_lines;
le = re = zoom_end_y_lines;
}
if ((vf) && (vf->type & VIDTYPE_MVC)) {
if (is_need_framepacking_output()) {
VSYNC_WR_MPEG_REG(
VD1_IF0_LUMA_Y0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD1_IF0_CHROMA_Y0 + cur_dev->viu_off,
((ls / 2) << VDIF_PIC_START_BIT) |
((le / 2) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_Y0 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_Y0 + cur_dev->viu_off,
((rs / 2) << VDIF_PIC_START_BIT) |
((re / 2) << VDIF_PIC_END_BIT));
} else {
VSYNC_WR_MPEG_REG(
VD1_IF0_LUMA_Y0 + cur_dev->viu_off,
(ls * 2 << VDIF_PIC_START_BIT) |
((le * 2 - 1) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD1_IF0_CHROMA_Y0 + cur_dev->viu_off,
((ls) << VDIF_PIC_START_BIT) |
((le - 1) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_Y0 + cur_dev->viu_off,
(ls * 2 << VDIF_PIC_START_BIT) |
((le * 2 - 1) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_Y0 + cur_dev->viu_off,
((ls) << VDIF_PIC_START_BIT) |
((le - 1) << VDIF_PIC_END_BIT));
}
} else {
VSYNC_WR_MPEG_REG(
VD1_IF0_LUMA_Y0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD1_IF0_CHROMA_Y0 + cur_dev->viu_off,
((ls / 2) << VDIF_PIC_START_BIT) |
((le / 2) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD1_IF0_LUMA_Y1 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD1_IF0_CHROMA_Y1 + cur_dev->viu_off,
((rs / 2) << VDIF_PIC_START_BIT) |
((re / 2) << VDIF_PIC_END_BIT));
#ifdef VIDEO_PIP
if (!cur_pipbuf)
#endif
{
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_Y0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_Y0 + cur_dev->viu_off,
((ls / 2) << VDIF_PIC_START_BIT) |
((le / 2) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_Y1 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_Y1 + cur_dev->viu_off,
((rs / 2) << VDIF_PIC_START_BIT) |
((re / 2) << VDIF_PIC_END_BIT));
}
}
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
int t_aligned;
int b_aligned;
int ori_t_aligned;
int ori_b_aligned;
int v_skip = cur_frame_par->vscale_skip_count + 1;
int c_skip = 2;
/* After TL1, afbc supports 420/422/444*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
if (vf && ((vf->type & VIDTYPE_VIU_444)
|| (vf->type & VIDTYPE_VIU_422)))
c_skip = 1;
t_aligned = round_down(zoom_start_y_lines, 4);
b_aligned = round_up(zoom_end_y_lines + 1, 4);
ori_t_aligned = round_down(ori_start_y_lines, 4);
ori_b_aligned = round_up(ori_end_y_lines + 1, 4);
VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_H,
(b_aligned - t_aligned) / c_skip / v_skip);
if (((process_3d_type & MODE_3D_FA)
|| (process_3d_type & MODE_FORCE_3D_FA_TB))
&& (cur_frame_par->vpp_3d_mode == 2)) {
int block_h;
block_h = ori_b_aligned - ori_t_aligned;
block_h = block_h / 8;
if (toggle_3d_fa_frame == OUT_FA_B_FRAME) {
VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE,
(((ori_t_aligned / 4) + block_h) << 16) |
((ori_b_aligned / 4) - 1));
} else {
VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE,
((ori_t_aligned / 4) << 16) |
((ori_t_aligned / 4) + block_h - 1));
}
} else {
VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE,
((t_aligned / 4) << 16) |
((b_aligned / 4) - 1));
}
VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE,
((zoom_start_y_lines - t_aligned) << 16) |
(zoom_end_y_lines - t_aligned));
/* afbc pixel vertical output region must be
* [0, zoom_end_y_lines - zoom_start_y_lines]
*/
VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE,
(zoom_end_y_lines - zoom_start_y_lines));
VSYNC_WR_MPEG_REG(AFBC_SIZE_IN,
(VSYNC_RD_MPEG_REG(AFBC_SIZE_IN)
& 0xffff0000) |
(ori_b_aligned - ori_t_aligned));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT,
(VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) &
0xffff0000) |
((b_aligned - t_aligned) / v_skip));
}
}
}
static void vd2_zoom_display_vert(struct vframe_s *vf, int vscale)
{
u32 ls, le, rs, re;
ls = rs = zoom2_start_y_lines;
le = re = zoom2_end_y_lines;
/* vd2 */
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_Y0 + cur_dev->viu_off,
(ls << VDIF_PIC_START_BIT) |
(le << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_Y0 + cur_dev->viu_off,
((ls / 2) << VDIF_PIC_START_BIT) |
((le / 2) << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_Y1 + cur_dev->viu_off,
(rs << VDIF_PIC_START_BIT) |
(re << VDIF_PIC_END_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_Y1 + cur_dev->viu_off,
((rs / 2) << VDIF_PIC_START_BIT) |
((re / 2) << VDIF_PIC_END_BIT));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
int t_aligned;
int b_aligned;
int ori_t_aligned;
int ori_b_aligned;
int v_skip = vscale + 1;
int c_skip = 2;
/* After TL1, afbc supports 420/422/444*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
if (vf && ((vf->type & VIDTYPE_VIU_444)
|| (vf->type & VIDTYPE_VIU_422)))
c_skip = 1;
t_aligned = round_down(zoom2_start_y_lines, 4);
b_aligned = round_up(zoom2_end_y_lines + 1, 4);
ori_t_aligned = round_down(ori2_start_y_lines, 4);
ori_b_aligned = round_up(ori2_end_y_lines + 1, 4);
/* TODO: afbc setting only support 420 for now */
VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H,
(b_aligned - t_aligned) / c_skip / v_skip);
VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE,
((t_aligned / 4) << 16) |
((b_aligned / 4) - 1));
VSYNC_WR_MPEG_REG(VD2_AFBC_PIXEL_VER_SCOPE,
((zoom2_start_y_lines - t_aligned) << 16) |
(zoom2_end_y_lines - t_aligned));
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_IN,
(VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN)
& 0xffff0000) |
(ori_b_aligned - ori_t_aligned));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT,
(VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT)
& 0xffff0000) |
((b_aligned - t_aligned) / v_skip));
}
}
}
#ifdef TV_3D_FUNCTION_OPEN
/* judge the out mode is 240:LBRBLRBR or 120:LRLRLR */
static void judge_3d_fa_out_mode(void)
{
if ((process_3d_type & MODE_3D_OUT_FA_MASK)
&& pause_one_3d_fl_frame == 2)
toggle_3d_fa_frame = OUT_FA_B_FRAME;
else if ((process_3d_type & MODE_3D_OUT_FA_MASK)
&& pause_one_3d_fl_frame == 1)
toggle_3d_fa_frame = OUT_FA_A_FRAME;
else if ((process_3d_type & MODE_3D_OUT_FA_MASK)
&& pause_one_3d_fl_frame == 0) {
/* toggle_3d_fa_frame determine*/
/*the out frame is L or R or blank */
if ((process_3d_type & MODE_3D_OUT_FA_L_FIRST)) {
if ((vsync_count % 2) == 0)
toggle_3d_fa_frame = OUT_FA_A_FRAME;
else
toggle_3d_fa_frame = OUT_FA_B_FRAME;
} else if ((process_3d_type & MODE_3D_OUT_FA_R_FIRST)) {
if ((vsync_count % 2) == 0)
toggle_3d_fa_frame = OUT_FA_B_FRAME;
else
toggle_3d_fa_frame = OUT_FA_A_FRAME;
} else if ((process_3d_type & MODE_3D_OUT_FA_LB_FIRST)) {
if ((vsync_count % 4) == 0)
toggle_3d_fa_frame = OUT_FA_A_FRAME;
else if ((vsync_count % 4) == 2)
toggle_3d_fa_frame = OUT_FA_B_FRAME;
else
toggle_3d_fa_frame = OUT_FA_BANK_FRAME;
} else if ((process_3d_type & MODE_3D_OUT_FA_RB_FIRST)) {
if ((vsync_count % 4) == 0)
toggle_3d_fa_frame = OUT_FA_B_FRAME;
else if ((vsync_count % 4) == 2)
toggle_3d_fa_frame = OUT_FA_A_FRAME;
else
toggle_3d_fa_frame = OUT_FA_BANK_FRAME;
}
} else
toggle_3d_fa_frame = OUT_FA_A_FRAME;
}
#endif
static void vframe_canvas_set(struct canvas_config_s *config, u32 planes,
u32 *index)
{
int i;
u32 *canvas_index = index;
struct canvas_config_s *cfg = config;
for (i = 0; i < planes; i++, canvas_index++, cfg++)
canvas_config_config(*canvas_index, cfg);
}
#ifdef PTS_LOGGING
static void log_vsync_video_pattern(int pattern)
{
int factor1 = 0, factor2 = 0, pattern_range = 0;
if (pattern >= PTS_MAX_NUM_PATTERNS)
return;
if (pattern == PTS_32_PATTERN) {
factor1 = 3;
factor2 = 2;
pattern_range = PTS_32_PATTERN_DETECT_RANGE;
} else if (pattern == PTS_22_PATTERN) {
factor1 = 2;
factor2 = 2;
pattern_range = PTS_22_PATTERN_DETECT_RANGE;
} else if (pattern == PTS_41_PATTERN) {
/* update 2111 mode detection */
if (pts_trace == 2) {
if ((pts_41_pattern_sink[1] == 1) &&
(pts_41_pattern_sink[2] == 1) &&
(pts_41_pattern_sink[3] == 1) &&
(pts_pattern[PTS_41_PATTERN] <
PTS_41_PATTERN_DETECT_RANGE)) {
pts_pattern[PTS_41_PATTERN]++;
if (pts_pattern[PTS_41_PATTERN] ==
PTS_41_PATTERN_DETECT_RANGE) {
pts_pattern_enter_cnt[PTS_41_PATTERN]++;
pts_pattern_detected = pattern;
if (pts_log_enable[PTS_41_PATTERN])
pr_info("video 4:1 mode detected\n");
}
}
pts_41_pattern_sink[0] = 2;
pts_41_pattern_sink_index = 1;
} else if (pts_trace == 1) {
if ((pts_41_pattern_sink_index <
PTS_41_PATTERN_SINK_MAX) &&
(pts_41_pattern_sink_index > 0)) {
pts_41_pattern_sink[pts_41_pattern_sink_index]
= 1;
pts_41_pattern_sink_index++;
} else if (pts_pattern[PTS_41_PATTERN] ==
PTS_41_PATTERN_DETECT_RANGE) {
pts_pattern[PTS_41_PATTERN] = 0;
pts_41_pattern_sink_index = 0;
pts_pattern_exit_cnt[PTS_41_PATTERN]++;
memset(&pts_41_pattern_sink[0], 0,
PTS_41_PATTERN_SINK_MAX);
if (pts_log_enable[PTS_41_PATTERN])
pr_info("video 4:1 mode broken\n");
} else {
pts_pattern[PTS_41_PATTERN] = 0;
pts_41_pattern_sink_index = 0;
memset(&pts_41_pattern_sink[0], 0,
PTS_41_PATTERN_SINK_MAX);
}
} else if (pts_pattern[PTS_41_PATTERN] ==
PTS_41_PATTERN_DETECT_RANGE) {
pts_pattern[PTS_41_PATTERN] = 0;
pts_41_pattern_sink_index = 0;
memset(&pts_41_pattern_sink[0], 0,
PTS_41_PATTERN_SINK_MAX);
pts_pattern_exit_cnt[PTS_41_PATTERN]++;
if (pts_log_enable[PTS_41_PATTERN])
pr_info("video 4:1 mode broken\n");
} else {
pts_pattern[PTS_41_PATTERN] = 0;
pts_41_pattern_sink_index = 0;
memset(&pts_41_pattern_sink[0], 0,
PTS_41_PATTERN_SINK_MAX);
}
return;
}
/* update 3:2 or 2:2 mode detection */
if (((pre_pts_trace == factor1) && (pts_trace == factor2)) ||
((pre_pts_trace == factor2) && (pts_trace == factor1))) {
if (pts_pattern[pattern] < pattern_range) {
pts_pattern[pattern]++;
if (pts_pattern[pattern] == pattern_range) {
pts_pattern_enter_cnt[pattern]++;
pts_pattern_detected = pattern;
if (pts_log_enable[pattern])
pr_info("video %d:%d mode detected\n",
factor1, factor2);
}
}
} else if (pts_pattern[pattern] == pattern_range) {
pts_pattern[pattern] = 0;
pts_pattern_exit_cnt[pattern]++;
if (pts_log_enable[pattern])
pr_info("video %d:%d mode broken\n", factor1, factor2);
} else
pts_pattern[pattern] = 0;
}
static void vsync_video_pattern(void)
{
/* Check for 3:2*/
log_vsync_video_pattern(PTS_32_PATTERN);
/* Check for 2:2*/
log_vsync_video_pattern(PTS_22_PATTERN);
/* Check for 4:1*/
log_vsync_video_pattern(PTS_41_PATTERN);
}
#endif
static inline void vd1_path_select(bool afbc)
{
u32 misc_off = cur_dev->vpp_off;
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG_BITS(
VD1_AFBCD0_MISC_CTRL,
/* go field sel */
(0 << 20) |
/* linebuffer en */
(0 << 16) |
/* vd1 -> dolby -> vpp top */
(0 << 14) |
/* axi sel: vd1 mif or afbc */
((afbc ? 1 : 0) << 12) |
/* data sel: vd1 & afbc0 (not osd4) */
(0 << 11) |
/* data sel: afbc0 or vd1 */
((afbc ? 1 : 0) << 10) |
/* afbc0 to vd1 (not di) */
(0 << 9) |
/* vd1 mif to vpp (not di) */
(0 << 8) |
/* afbc0 gclk ctrl */
(0 << 0),
0, 22);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
VSYNC_WR_MPEG_REG_BITS(
VD1_AFBCD0_MISC_CTRL,
/* Vd1_afbc0_mem_sel */
(afbc ? 1 : 0),
22, 1);
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
return;
if ((DI_POST_REG_RD(DI_POST_CTRL) & 0x100) != 0) {
/* check di_vpp_out_en bit */
VSYNC_WR_MPEG_REG_BITS(
VD1_AFBCD0_MISC_CTRL,
/* vd1 mif to di */
1,
8, 2);
VSYNC_WR_MPEG_REG_BITS(
VD1_AFBCD0_MISC_CTRL,
/* go field select di post */
1,
20, 2);
}
#endif
} else {
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
if ((DI_POST_REG_RD(DI_POST_CTRL) & 0x100) == 0)
/* mif sel */
#endif
VSYNC_WR_MPEG_REG_BITS(
VIU_MISC_CTRL0 + misc_off,
0, 16, 3);
VSYNC_WR_MPEG_REG_BITS(
VIU_MISC_CTRL0 + misc_off,
(afbc ? 1 : 0), 20, 1);
}
}
static inline void vd2_path_select(bool afbc)
{
u32 misc_off = cur_dev->vpp_off;
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG_BITS(
VD2_AFBCD1_MISC_CTRL,
/* go field sel */
(0 << 20) |
/* linebuffer en */
(0 << 16) |
/* TODO: vd2 -> dolby -> vpp top ?? */
(0 << 14) |
/* axi sel: vd2 mif */
((afbc ? 1 : 0) << 12) |
/* data sel: vd2 & afbc1 (not osd4) */
(0 << 11) |
/* data sel: afbc1 */
((afbc ? 1 : 0) << 10) |
/* afbc1 to vd2 (not di) */
(0 << 9) |
/* vd2 mif to vpp (not di) */
(0 << 8) |
/* afbc1 gclk ctrl */
(0 << 0),
0, 22);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
VSYNC_WR_MPEG_REG_BITS(
VD2_AFBCD1_MISC_CTRL,
/* Vd2_afbc0_mem_sel */
(afbc ? 1 : 0),
22, 1);
} else {
VSYNC_WR_MPEG_REG_BITS(
VIU_MISC_CTRL1 + misc_off,
(afbc ? 2 : 0), 0, 2);
}
}
#ifdef VIDEO_PIP
s32 config_vd_pps(
u8 layer_id,
struct vpp_frame_par_s *cur_frame_par,
struct scaler_setting_s *setting,
const struct vinfo_s *info)
{
struct vppfilter_mode_s *vpp_filter;
if (!cur_frame_par || !info || !setting)
return -1;
vpp_filter = &cur_frame_par->vpp_filter;
setting->frame_par = cur_frame_par;
setting->id = layer_id;
setting->misc_reg_offt = 0;
/* enable pps as default */
setting->sc_top_enable = true;
setting->sc_h_enable = true;
setting->sc_v_enable = true;
if ((vpp_filter->vpp_hsc_start_phase_step == 0x1000000)
&& (vpp_filter->vpp_vsc_start_phase_step == 0x1000000)
&& (vpp_filter->vpp_hsc_start_phase_step ==
vpp_filter->vpp_hf_start_phase_step)
&& !vpp_filter->vpp_pre_vsc_en
&& !vpp_filter->vpp_pre_hsc_en
&& !cur_frame_par->supsc0_enable
&& !cur_frame_par->supsc1_enable
&& bypass_pps)
setting->sc_top_enable = false;
/* old chip: vd2 has no pps */
if ((legacy_vpp || is_meson_tl1_cpu())
&& (setting->id != 0))
setting->sc_top_enable = false;
setting->vinfo_width = info->width;
setting->vinfo_height = info->height;
return 0;
}
static inline void vd2_scaler_setting(
struct scaler_setting_s *setting)
{
u32 misc_off, i;
u32 r1, r2, r3;
struct vpp_frame_par_s *frame_par;
struct vppfilter_mode_s *vpp_filter;
if (legacy_vpp || !setting
|| !setting->frame_par
|| is_meson_tl1_cpu())
return;
frame_par = setting->frame_par;
misc_off = setting->misc_reg_offt;
vpp_filter = &frame_par->vpp_filter;
if (setting->sc_top_enable) {
u32 sc_misc_val;
sc_misc_val = VPP_SC_TOP_EN | VPP_SC_V1OUT_EN;
if (setting->sc_h_enable) {
sc_misc_val |= (((vpp_filter->vpp_pre_hsc_en & 1)
<< VPP_SC_PREHORZ_EN_BIT)
| VPP_SC_HORZ_EN);
sc_misc_val |= ((vpp_filter->vpp_horz_coeff[0] & 7)
<< VPP_SC_HBANK_LENGTH_BIT);
}
if (setting->sc_v_enable) {
sc_misc_val |= (((vpp_filter->vpp_pre_vsc_en & 1)
<< VPP_SC_PREVERT_EN_BIT)
| VPP_SC_VERT_EN);
sc_misc_val |= ((vpp_filter->vpp_pre_vsc_en & 1)
<< VPP_LINE_BUFFER_EN_BIT);
sc_misc_val |= ((vpp_filter->vpp_vert_coeff[0] & 7)
<< VPP_SC_VBANK_LENGTH_BIT);
}
VSYNC_WR_MPEG_REG(
VD2_SC_MISC + misc_off,
sc_misc_val);
} else {
setting->sc_v_enable = false;
setting->sc_h_enable = false;
VSYNC_WR_MPEG_REG_BITS(
VD2_SC_MISC + misc_off,
0, VPP_SC_TOP_EN_BIT,
VPP_SC_TOP_EN_WID);
}
/* horitontal filter settings */
if (setting->sc_h_enable) {
if (vpp_filter->vpp_horz_coeff[1] & 0x8000) {
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF_IDX + misc_off,
VPP_COEF_HORZ | VPP_COEF_9BIT);
} else {
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF_IDX + misc_off,
VPP_COEF_HORZ);
}
for (i = 0; i <
(vpp_filter->vpp_horz_coeff[1] & 0xff); i++) {
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF + misc_off,
vpp_filter->vpp_horz_coeff[i + 2]);
}
r1 = frame_par->VPP_hsc_linear_startp
- frame_par->VPP_hsc_startp;
r2 = frame_par->VPP_hsc_linear_endp
- frame_par->VPP_hsc_startp;
r3 = frame_par->VPP_hsc_endp
- frame_par->VPP_hsc_startp;
VSYNC_WR_MPEG_REG_BITS(
VD2_HSC_PHASE_CTRL + misc_off,
frame_par->VPP_hf_ini_phase_,
VPP_HSC_TOP_INI_PHASE_BIT,
VPP_HSC_TOP_INI_PHASE_WID);
VSYNC_WR_MPEG_REG(
VD2_HSC_REGION12_STARTP + misc_off,
(0 << VPP_REGION1_BIT) |
((r1 & VPP_REGION_MASK)
<< VPP_REGION2_BIT));
VSYNC_WR_MPEG_REG(
VD2_HSC_REGION34_STARTP + misc_off,
((r2 & VPP_REGION_MASK)
<< VPP_REGION3_BIT) |
((r3 & VPP_REGION_MASK)
<< VPP_REGION4_BIT));
VSYNC_WR_MPEG_REG(
VD2_HSC_REGION4_ENDP + misc_off, r3);
VSYNC_WR_MPEG_REG(
VD2_HSC_START_PHASE_STEP + misc_off,
vpp_filter->vpp_hf_start_phase_step);
VSYNC_WR_MPEG_REG(
VD2_HSC_REGION1_PHASE_SLOPE + misc_off,
vpp_filter->vpp_hf_start_phase_slope);
VSYNC_WR_MPEG_REG(
VD2_HSC_REGION3_PHASE_SLOPE + misc_off,
vpp_filter->vpp_hf_end_phase_slope);
}
/* vertical filter settings */
if (setting->sc_v_enable) {
VSYNC_WR_MPEG_REG_BITS(
VD2_VSC_PHASE_CTRL + misc_off,
(vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0,
VPP_PHASECTL_DOUBLELINE_BIT,
VPP_PHASECTL_DOUBLELINE_WID);
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF_IDX + misc_off,
VPP_COEF_VERT);
for (i = 0; i < vpp_filter->vpp_vert_coeff[1]; i++) {
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF + misc_off,
vpp_filter->vpp_vert_coeff[i + 2]);
}
/* vertical chroma filter settings */
if (vpp_filter->vpp_vert_chroma_filter_en) {
const u32 *pCoeff =
vpp_filter->vpp_vert_chroma_coeff;
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF_IDX + misc_off,
VPP_COEF_VERT_CHROMA
|VPP_COEF_SEP_EN);
for (i = 0; i < pCoeff[1]; i++)
VSYNC_WR_MPEG_REG(
VD2_SCALE_COEF + misc_off,
pCoeff[i + 2]);
}
r1 = frame_par->VPP_vsc_endp
- frame_par->VPP_vsc_startp;
VSYNC_WR_MPEG_REG(
VD2_VSC_REGION12_STARTP + misc_off, 0);
VSYNC_WR_MPEG_REG(
VD2_VSC_REGION34_STARTP + misc_off,
((r1 & VPP_REGION_MASK)
<< VPP_REGION3_BIT) |
((r1 & VPP_REGION_MASK)
<< VPP_REGION4_BIT));
VSYNC_WR_MPEG_REG(
VD2_VSC_REGION4_ENDP + misc_off, r1);
VSYNC_WR_MPEG_REG(
VD2_VSC_START_PHASE_STEP + misc_off,
vpp_filter->vpp_vsc_start_phase_step);
}
VSYNC_WR_MPEG_REG(
VPP_VD2_HDR_IN_SIZE + misc_off,
(frame_par->VPP_pic_in_height_ << 16)
| frame_par->VPP_line_in_length_);
}
s32 config_vd_blend(
u8 layer_id,
struct vpp_frame_par_s *cur_frame_par,
struct vframe_s *vf,
u32 layer_alpha,
struct blend_setting_s *setting)
{
/* u32 type = 0; */
u32 vskip, hskip;
if (!cur_frame_par || !setting || !vf)
return -1;
setting->frame_par = cur_frame_par;
setting->id = layer_id;
setting->misc_reg_offt = 0;
setting->layer_alpha = layer_alpha;
setting->preblend_h_start = 0;
setting->preblend_h_end = 4096;
if ((cur_frame_par->VPP_post_blend_vd_v_end_ -
cur_frame_par->VPP_post_blend_vd_v_start_ + 1)
> VPP_PREBLEND_VD_V_END_LIMIT) {
setting->preblend_v_start =
cur_frame_par->VPP_post_blend_vd_v_start_;
setting->preblend_v_end =
cur_frame_par->VPP_post_blend_vd_v_end_;
} else {
setting->preblend_v_start = 0;
setting->preblend_v_end =
VPP_PREBLEND_VD_V_END_LIMIT - 1;
}
setting->preblend_h_size =
cur_frame_par->VPP_line_in_length_;
/* old chip, vd2 has no scaler, so only can use mif setting */
if ((setting->id != 0) &&
(legacy_vpp || is_meson_tl1_cpu())) {
vskip = cur_frame_par->vscale_skip_count;
hskip = cur_frame_par->hscale_skip_count;
setting->postblend_h_start =
cur_frame_par->VPP_hd_start_lines_;
setting->postblend_h_end =
cur_frame_par->VPP_hd_start_lines_ +
(cur_frame_par->VPP_line_in_length_ >> hskip) - 1;
setting->postblend_v_start =
cur_frame_par->VPP_vd_start_lines_;
setting->postblend_v_end =
cur_frame_par->VPP_vd_start_lines_ +
(cur_frame_par->VPP_pic_in_height_ >> vskip) - 1;
setting->postblend_h_size =
cur_frame_par->VPP_post_blend_h_size_;
} else {
setting->postblend_h_start =
cur_frame_par->VPP_hsc_startp;
setting->postblend_h_end =
cur_frame_par->VPP_hsc_endp;
setting->postblend_v_start =
cur_frame_par->VPP_vsc_startp;
setting->postblend_v_end =
cur_frame_par->VPP_vsc_endp;
setting->postblend_h_size =
cur_frame_par->VPP_post_blend_h_size_;
}
if (!legacy_vpp) {
u32 temp_h = cur_frame_par->VPP_pic_in_height_;
temp_h <<= 16;
setting->preblend_h_size |= temp_h;
temp_h =
cur_frame_par->VPP_post_blend_vd_v_end_ + 1;
temp_h <<= 16;
setting->postblend_h_size |= temp_h;
}
#if 0
/* TODO: need remove this work around check for afbc */
type = vf->type;
if (cur_frame_par->nocomp)
type &= ~VIDTYPE_COMPRESS;
if (type & VIDTYPE_COMPRESS) {
u32 v_phase;
struct vppfilter_mode_s *vpp_filter =
&cur_frame_par->vpp_filter;
v_phase = vpp_filter->vpp_vsc_start_phase_step;
v_phase *= (cur_frame_par->vscale_skip_count + 1);
if ((v_phase > 0x1000000) &&
(layer->disp_info.layer_top < 0)) {
if ((cur_frame_par->VPP_vsc_endp > 0x6) &&
((cur_frame_par->VPP_vsc_endp < 0x250)
|| (cur_frame_par->VPP_vsc_endp <
cur_frame_par->VPP_post_blend_vd_v_end_/2))) {
setting->postblend_v_end -= 6;
}
}
}
#endif
return 0;
}
static inline void vd2_vpp_blend_setting(
struct blend_setting_s *setting)
{
u32 misc_off;
u32 vd_size_mask = VPP_VD_SIZE_MASK;
if (!setting)
return;
/* g12a change to 13 bits */
if (!legacy_vpp)
vd_size_mask = 0x1fff;
misc_off = 0;
/* vd2 preblend size should be same postblend size */
/* preblend setting */
VSYNC_WR_MPEG_REG(
VPP_BLEND_VD2_H_START_END + misc_off,
((setting->postblend_h_start & vd_size_mask)
<< VPP_VD1_START_BIT) |
((setting->postblend_h_end & vd_size_mask)
<< VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(
VPP_BLEND_VD2_V_START_END + misc_off,
((setting->postblend_v_start & vd_size_mask)
<< VPP_VD1_START_BIT) |
((setting->postblend_v_end & vd_size_mask)
<< VPP_VD1_END_BIT));
}
static inline void proc_vd2_vsc_phase_per_vsync(
struct vpp_frame_par_s *frame_par,
struct vframe_s *vf,
u32 vout_type)
{
struct f2v_vphase_s *vphase;
u32 misc_off, vin_type;
struct vppfilter_mode_s *vpp_filter;
if (legacy_vpp || is_meson_tl1_cpu()
|| !frame_par || !vf)
return;
vpp_filter = &frame_par->vpp_filter;
misc_off = 0;
vin_type = vf->type & VIDTYPE_TYPEMASK;
/* vertical phase */
vphase = &frame_par->VPP_vf_ini_phase_
[vpp_phase_table[vin_type]
[vout_type]];
VSYNC_WR_MPEG_REG(
VD2_VSC_INI_PHASE + misc_off,
((u32) (vphase->phase) << 8));
if (vphase->repeat_skip >= 0) {
/* skip lines */
VSYNC_WR_MPEG_REG_BITS(
VD2_VSC_PHASE_CTRL + misc_off,
skip_tab[vphase->repeat_skip],
VPP_PHASECTL_INIRCVNUMT_BIT,
VPP_PHASECTL_INIRCVNUM_WID +
VPP_PHASECTL_INIRPTNUM_WID);
} else {
/* repeat first line */
VSYNC_WR_MPEG_REG_BITS(
VD2_VSC_PHASE_CTRL + misc_off,
4,
VPP_PHASECTL_INIRCVNUMT_BIT,
VPP_PHASECTL_INIRCVNUM_WID);
VSYNC_WR_MPEG_REG_BITS(
VD2_VSC_PHASE_CTRL + misc_off,
1 - vphase->repeat_skip,
VPP_PHASECTL_INIRPTNUMT_BIT,
VPP_PHASECTL_INIRPTNUM_WID);
}
VSYNC_WR_MPEG_REG_BITS(
VD2_VSC_PHASE_CTRL + misc_off,
(vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0,
VPP_PHASECTL_DOUBLELINE_BIT,
VPP_PHASECTL_DOUBLELINE_WID);
}
static void pip_toggle_frame(struct vframe_s *vf)
{
u32 first_picture = 0;
bool force_toggle = false;
if (vf == NULL)
return;
ori2_start_x_lines = 0;
ori2_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ?
vf->compWidth : vf->width) - 1;
ori2_start_y_lines = 0;
ori2_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ?
vf->compHeight : vf->height) - 1;
if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME)
pr_info("%s()\n", __func__);
if ((vf->width == 0) || (vf->height == 0)) {
amlog_level(LOG_LEVEL_ERROR,
"Video: invalid frame dimension\n");
return;
}
if (cur_pipbuf
&& (cur_pipbuf != &local_pip)
&& (cur_pipbuf != vf)) {
pip_frame_count++;
if (pip_frame_count == 1)
first_picture = 1;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_vsync_rdma_enable()) {
if (pip_rdma_buf == cur_pipbuf)
pipbuf_to_put = cur_pipbuf;
else
pip_vf_put(cur_pipbuf);
} else {
if (pipbuf_to_put) {
pip_vf_put(
pipbuf_to_put);
pipbuf_to_put = NULL;
}
pip_vf_put(cur_pipbuf);
}
#else
pip_vf_put(cur_pipbuf);
#endif
} else if (!cur_pipbuf
|| (cur_pipbuf == &local_pip))
first_picture = 1;
/* switch buffer */
if (vf->type & VIDTYPE_COMPRESS) {
VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR,
vf->compHeadAddr>>4);
VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR,
vf->compBodyAddr>>4);
}
if (vf->canvas0Addr != 0) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (vf->canvas0Addr != (u32)-1) {
canvas_copy(vf->canvas0Addr & 0xff,
disp_canvas_index[pip_rdma_canvas_id][3]);
canvas_copy((vf->canvas0Addr >> 8) & 0xff,
disp_canvas_index[pip_rdma_canvas_id][4]);
canvas_copy((vf->canvas0Addr >> 16) & 0xff,
disp_canvas_index[pip_rdma_canvas_id][5]);
} else {
vframe_canvas_set(&vf->canvas0_config[0],
vf->plane_num,
&disp_canvas_index[pip_rdma_canvas_id][3]);
}
VSYNC_WR_MPEG_REG(
VD2_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[pip_rdma_canvas_id][1]);
pip_next_rdma_canvas_id = pip_rdma_canvas_id ? 0 : 1;
#endif
}
if (cur_pipbuf &&
(cur_pipbuf->ratio_control &
DISP_RATIO_ADAPTED_PICMODE)) {
if (vf && (cur_pipbuf->ratio_control
== vf->ratio_control)
&& memcmp(&cur_pipbuf->pic_mode,
&vf->pic_mode,
sizeof(struct vframe_pic_mode_s)))
force_toggle = true;
else if (memcmp(&cur_pipbuf->pic_mode,
&gPic_info[1],
sizeof(struct vframe_pic_mode_s)))
force_toggle = true;
}
if (pip_property_changed) {
first_picture = 1;
pip_property_changed = 0;
}
if (cur_pipbuf != vf)
vf->type_backup = vf->type;
/* enable new config on the new frames */
if (first_picture || force_toggle ||
(cur_pipbuf &&
((cur_pipbuf->bufWidth != vf->bufWidth) ||
(cur_pipbuf->width != vf->width) ||
(cur_pipbuf->height != vf->height) ||
(cur_pipbuf->bitdepth != vf->bitdepth) ||
(cur_pipbuf->trans_fmt != vf->trans_fmt) ||
(cur_pipbuf->ratio_control != vf->ratio_control) ||
((cur_pipbuf->type_backup & VIDTYPE_INTERLACE) !=
(vf->type_backup & VIDTYPE_INTERLACE)) ||
(cur_pipbuf->type != vf->type)))) {
int iret;
/* apply new vpp settings */
nextpip_frame_par =
(&pip_frame_parms[0] == nextpip_frame_par) ?
&pip_frame_parms[1] : &pip_frame_parms[0];
update_layer_info(1);
if (legacy_vpp || is_meson_tl1_cpu())
iret = vpp_set_filters_no_scaler(
&glayer_info[1], vf,
nextpip_frame_par, vinfo, 1);
else
iret = vpp_set_filters(
&glayer_info[1], vf,
nextpip_frame_par, vinfo,
true, 1);
memcpy(&gPic_info[1], &vf->pic_mode,
sizeof(struct vframe_pic_mode_s));
if (iret == VppFilter_Success_and_Changed)
pip_property_changed = 1;
pip_frame_ready_to_set = 1;
}
if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) &&
(!pip_property_changed || (vf != cur_pipbuf))) {
if (disable_videopip == VIDEO_DISABLE_FORNEXT) {
EnableVideoLayer2();
disable_videopip = VIDEO_DISABLE_NONE;
}
if (first_picture &&
(disable_videopip !=
VIDEO_DISABLE_NORMAL)) {
EnableVideoLayer2();
}
}
cur_pipbuf = vf;
if (first_picture)
pip_frame_ready_to_set = 1;
if (cur_pipbuf != &local_pip)
video_pip_keeper_new_frame_notify();
}
static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
{
u32 r;
u32 vphase, vini_phase;
u32 pat, loop;
static const u32 vpat[MAX_VSKIP_COUNT + 1] = {
0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
u32 u, v;
u32 type, bit_mode = 0;
if (!vf || !frame_par) {
pr_err("pip_set_dcu vf is NULL\n");
return;
}
type = vf->type;
pr_debug("pip_set_dcu %p, type:0x%x\n", vf, type);
if (frame_par->nocomp)
type &= ~VIDTYPE_COMPRESS;
if (type & VIDTYPE_COMPRESS) {
r = (3 << 24) |
(vpp_hold_line << 16) |
((legacy_vpp ? 1 : 2) << 14) | /* burst1 */
(vf->bitdepth & BITDEPTH_MASK);
if (frame_par->hscale_skip_count)
r |= 0x33;
if (frame_par->vscale_skip_count)
r |= 0xcc;
#ifdef TV_REVERSE
if (reverse)
r |= (1<<26) | (1<<27);
#endif
if (vf->bitdepth & BITDEPTH_SAVING_MODE)
r |= (1<<28); /* mem_saving_mode */
if (type & VIDTYPE_SCATTER)
r |= (1<<29);
VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r);
r = 0x1700;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (vf && (vf->source_type
!= VFRAME_SOURCE_TYPE_HDMI))
r |= (1 << 19); /* dos_uncomp */
}
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, r);
r = 0x100;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (type & VIDTYPE_VIU_444)
r |= 0;
else if (type & VIDTYPE_VIU_422)
r |= (1 << 12);
else
r |= (2 << 12);
}
VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r);
u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3;
v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3;
VSYNC_WR_MPEG_REG(VD2_AFBC_DEC_DEF_COLOR,
0x3FF00000 | /*Y,bit20+*/
0x80 << (u + 10) |
0x80 << v);
/* chroma formatter */
r = HFORMATTER_EN |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
#if 0 /* def CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
r |= HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_ALWAYS_RPT |
(0 << VFORMATTER_INIPHASE_BIT) |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
} else
#endif
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
r = HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
if (is_dolby_vision_on())
r |= HFORMATTER_REPEAT |
(0xc << VFORMATTER_INIPHASE_BIT);
else
r |= HFORMATTER_RRT_PIXEL0 |
(0 << VFORMATTER_INIPHASE_BIT);
if (type & VIDTYPE_VIU_444) {
r &= ~HFORMATTER_EN;
r &= ~VFORMATTER_EN;
r &= ~HFORMATTER_YC_RATIO_2_1;
} else if (type & VIDTYPE_VIU_422) {
r &= ~VFORMATTER_EN;
}
} else {
r = HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
if (is_dolby_vision_on())
r |= HFORMATTER_REPEAT |
(0xc << VFORMATTER_INIPHASE_BIT);
else
r |= HFORMATTER_RRT_PIXEL0 |
(0 << VFORMATTER_INIPHASE_BIT);
}
VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (type & VIDTYPE_COMPRESS_LOSS)
VSYNC_WR_MPEG_REG(
VD2_AFBCDEC_IQUANT_ENABLE,
((1 << 11) |
(1 << 10) |
(1 << 4) |
(1 << 0)));
else
VSYNC_WR_MPEG_REG(
VD2_AFBCDEC_IQUANT_ENABLE, 0);
}
vd2_path_select(true);
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG +
cur_dev->viu_off, 0);
return;
}
if ((vf->bitdepth & BITDEPTH_Y10) &&
(!frame_par->nocomp)) {
if (vf->type & VIDTYPE_VIU_444) {
bit_mode = 2;
} else {
if (vf->bitdepth & FULL_PACK_422_MODE)
bit_mode = 3;
else
bit_mode = 1;
}
} else {
bit_mode = 0;
}
vd2_path_select(false);
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG_BITS(
G12_VD2_IF0_GEN_REG3,
(bit_mode & 0x3), 8, 2);
} else {
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG3 + cur_dev->viu_off,
(bit_mode&0x3), 8, 2);
}
if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1))
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
if (type & VIDTYPE_VIU_NV21)
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG2 +
cur_dev->viu_off, 1, 0, 1);
else
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG2 +
cur_dev->viu_off, 0, 0, 1);
r = (3 << VDIF_URGENT_BIT) |
(vpp_hold_line << VDIF_HOLD_LINES_BIT) |
VDIF_FORMAT_SPLIT |
VDIF_CHRO_RPT_LAST | VDIF_ENABLE;
/* | VDIF_RESET_ON_GO_FIELD;*/
if (debug_flag & DEBUG_FLAG_GOFIELD_MANUL)
r |= 1<<7; /*for manul triggle gofiled.*/
if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0)
r |= VDIF_SEPARATE_EN;
else {
if (type & VIDTYPE_VIU_422)
r |= VDIF_FORMAT_422;
else {
r |= VDIF_FORMAT_RGB888_YUV444 |
VDIF_DEMUX_MODE_RGB_444;
}
}
if (frame_par->hscale_skip_count)
r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, r);
#ifdef TV_REVERSE
if (reverse) {
VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 +
cur_dev->viu_off), 0xf, 2, 4);
} else {
VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 +
cur_dev->viu_off), 0, 2, 4);
}
#endif
/* chroma formatter */
if (type & VIDTYPE_VIU_444) {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_1_1);
} else if (type & VIDTYPE_VIU_FIELD) {
vini_phase = 0xc << VFORMATTER_INIPHASE_BIT;
vphase = ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT;
if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
is_meson_txlx_cpu()) {
if ((vf->width >= 3840) &&
(vf->height >= 2160) &&
(type & VIDTYPE_VIU_422)) {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_RRT_PIXEL0 |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase);
} else {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase |
VFORMATTER_EN);
}
} else {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase |
VFORMATTER_EN);
}
} else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xe << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
} else {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xc << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
}
if (is_meson_txlx_cpu()
|| cpu_after_eq(
MESON_CPU_MAJOR_ID_G12A))
VSYNC_WR_MPEG_REG_BITS(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
1, 29, 1);
/* LOOP/SKIP pattern */
pat = vpat[frame_par->vscale_skip_count];
if (type & VIDTYPE_VIU_FIELD) {
loop = 0;
if (type & VIDTYPE_INTERLACE)
pat = vpat[frame_par->vscale_skip_count >> 1];
} else if (type & VIDTYPE_MVC) {
loop = 0x11;
pat = 0x80;
} else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) {
loop = 0x11;
pat <<= 4;
} else
loop = 0;
VSYNC_WR_MPEG_REG(
VD2_IF0_RPT_LOOP + cur_dev->viu_off,
(loop << VDIF_CHROMA_LOOP1_BIT) |
(loop << VDIF_LUMA_LOOP1_BIT) |
(loop << VDIF_CHROMA_LOOP0_BIT) |
(loop << VDIF_LUMA_LOOP0_BIT));
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0);
}
#endif
/* for sdr/hdr/single dv switch with dual dv */
static u32 last_el_status;
/* for dual dv switch with different el size */
static u32 last_el_w;
bool has_enhanced_layer(struct vframe_s *vf)
{
struct provider_aux_req_s req;
if (!vf)
return 0;
if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS)
return 0;
if (!is_dolby_vision_on())
return 0;
req.vf = vf;
req.bot_flag = 0;
req.aux_buf = NULL;
req.aux_size = 0;
req.dv_enhance_exist = 0;
vf_notify_provider_by_name("dvbldec",
VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
(void *)&req);
return req.dv_enhance_exist;
}
u32 property_changed_true;
static bool has_receive_dummy_vframe(void)
{
int i;
struct vframe_s *vf;
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_num; i++) {
if (dispbuf_to_put[i]) {
video_vf_put(dispbuf_to_put[i]);
dispbuf_to_put[i] = NULL;
}
dispbuf_to_put_num = 0;
}
#endif
/* recycle the last vframe. */
if (cur_dispbuf)
video_vf_put(cur_dispbuf);
/*pr_info("put dummy vframe.\n");*/
video_vf_put(vf);
return true;
}
return false;
}
static u64 func_div(u64 number, u32 divid)
{
u64 tmp = number;
do_div(tmp, divid);
return tmp;
}
static void vsync_toggle_frame(struct vframe_s *vf, int line)
{
static u32 last_pts;
u32 diff_pts;
u32 first_picture = 0;
unsigned long flags = 0;
bool vf_with_el = false;
bool force_toggle = false;
long long *clk_array;
bool is_mvc = false;
ATRACE_COUNTER(__func__, line);
if (vf == NULL)
return;
ATRACE_COUNTER("vsync_toggle_frame_pts", vf->pts);
diff_pts = vf->pts - last_pts;
if (last_pts && diff_pts < 90000)
ATRACE_COUNTER("vsync_toggle_frame_inc", diff_pts);
else
ATRACE_COUNTER("vsync_toggle_frame_inc", 0); /* discontinue */
last_pts = vf->pts;
frame_count++;
toggle_count++;
if (vf->type & VIDTYPE_MVC)
is_mvc = true;
if (is_dolby_vision_enable())
vf_with_el = has_enhanced_layer(vf);
#ifdef PTS_TRACE_DEBUG
#ifdef PTS_TRACE_START
if (pts_trace_his_rd < 16) {
#endif
pts_trace_his[pts_trace_his_rd] = pts_trace;
pts_his[pts_trace_his_rd] = vf->pts;
scr_his[pts_trace_his_rd] = timestamp_pcrscr_get();
pts_trace_his_rd++;
if (pts_trace_his_rd >= 16)
pts_trace_his_rd = 0;
#ifdef PTS_TRACE_START
}
#endif
#endif
#ifdef PTS_LOGGING
if (pts_escape_vsync == 1) {
pts_trace++;
pts_escape_vsync = 0;
}
vsync_video_pattern();
pre_pts_trace = pts_trace;
#endif
#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG)
pts_trace = 0;
#endif
ori_start_x_lines = 0;
ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ?
vf->compWidth : vf->width) - 1;
ori_start_y_lines = 0;
ori_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ?
vf->compHeight : vf->height) - 1;
if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) {
u32 pcr = timestamp_pcrscr_get();
u32 vpts = timestamp_vpts_get();
u32 apts = timestamp_apts_get();
pr_info("%s pts:%d.%06d pcr:%d.%06d vpts:%d.%06d apts:%d.%06d\n",
__func__, (vf->pts) / 90000,
((vf->pts) % 90000) * 1000 / 90, (pcr) / 90000,
((pcr) % 90000) * 1000 / 90, (vpts) / 90000,
((vpts) % 90000) * 1000 / 90, (apts) / 90000,
((apts) % 90000) * 1000 / 90);
}
if (trickmode_i || trickmode_fffb)
trickmode_duration_count = trickmode_duration;
if (vf->early_process_fun) {
if (vf->early_process_fun(vf->private_data, vf) == 1) {
/* video_property_changed = true; */
first_picture = 1;
}
} else {
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) != 0) {
/* check mif enable status, disable post di */
VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30);
VSYNC_WR_MPEG_REG(DI_POST_SIZE,
(32 - 1) | ((128 - 1) << 16));
VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG,
READ_VCBUS_REG(DI_IF1_GEN_REG) &
0xfffffffe);
}
#endif
}
timer_count = 0;
if ((vf->width == 0) && (vf->height == 0)) {
amlog_level(LOG_LEVEL_ERROR,
"Video: invalid frame dimension\n");
ATRACE_COUNTER(__func__, __LINE__);
return;
}
if (hold_video) {
if (cur_dispbuf != vf) {
new_frame_count++;
if (vf->pts != 0) {
amlog_mask(LOG_MASK_TIMESTAMP,
"vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n",
vf->pts, timestamp_pcrscr_get(),
READ_MPEG_REG(SCR_HIU));
timestamp_vpts_set(vf->pts);
last_frame_duration = vf->duration;
} else if (last_frame_duration) {
amlog_mask(LOG_MASK_TIMESTAMP,
"vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n",
timestamp_vpts_get() +
DUR2PTS(cur_dispbuf->duration),
timestamp_pcrscr_get(),
READ_MPEG_REG(SCR_HIU));
timestamp_vpts_inc(DUR2PTS
(last_frame_duration));
vpts_remainder +=
DUR2PTS_RM(last_frame_duration);
if (vpts_remainder >= 0xf) {
vpts_remainder -= 0xf;
timestamp_vpts_inc(-1);
}
}
if (vf->type & VIDTYPE_COMPRESS) {
cur_width = vf->compWidth;
cur_height = vf->compHeight;
} else {
cur_width = vf->width;
cur_height = vf->height;
}
video_vf_put(vf);
ATRACE_COUNTER(__func__, __LINE__);
return;
}
}
if ((cur_dispbuf) && (cur_dispbuf != &vf_local) && (cur_dispbuf != vf)
&& (video_property_changed != 2)) {
new_frame_count++;
if (new_frame_count == 1)
first_picture = 1;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_vsync_rdma_enable()) {
#ifdef RDMA_RECYCLE_ORDERED_VFRAMES
if (dispbuf_to_put_num < DISPBUF_TO_PUT_MAX) {
dispbuf_to_put[dispbuf_to_put_num] =
cur_dispbuf;
dispbuf_to_put_num++;
} else
video_vf_put(cur_dispbuf);
#else
if (cur_rdma_buf == cur_dispbuf) {
dispbuf_to_put[0] = cur_dispbuf;
dispbuf_to_put_num = 1;
} else
video_vf_put(cur_dispbuf);
#endif
} else {
int i;
for (i = 0; i < dispbuf_to_put_num; i++) {
if (dispbuf_to_put[i]) {
video_vf_put(
dispbuf_to_put[i]);
dispbuf_to_put[i] = NULL;
}
dispbuf_to_put_num = 0;
}
video_vf_put(cur_dispbuf);
}
#else
video_vf_put(cur_dispbuf);
#endif
if (debug_flag & DEBUG_FLAG_LATENCY) {
vf->ready_clock[3] = sched_clock();
pr_info(
"video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n",
func_div(vf->ready_clock[3], 1000),
func_div(vf->ready_clock[2], 1000),
func_div(vf->ready_clock[1], 1000),
func_div(vf->ready_clock[0], 1000));
cur_dispbuf->ready_clock[4] = sched_clock();
clk_array = cur_dispbuf->ready_clock;
pr_info("video put latency %lld ms, video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n",
func_div(*(clk_array + 4), 1000),
func_div(*(clk_array + 3), 1000),
func_div(*(clk_array + 2), 1000),
func_div(*(clk_array + 1), 1000),
func_div(*clk_array, 1000));
}
} else
first_picture = 1;
if (video_property_changed) {
property_changed_true = 2;
video_property_changed = 0;
first_picture = 1;
}
if (property_changed_true > 0) {
property_changed_true--;
first_picture = 1;
}
if ((debug_flag & DEBUG_FLAG_BLACKOUT)
&& first_picture)
pr_info("first picture {%d,%d} pts:%x,\n",
vf->width, vf->height, vf->pts);
/* switch buffer */
post_canvas = vf->canvas0Addr;
if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) &&
(vf->type & VIDTYPE_COMPRESS)) {
VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4);
VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4);
}
if ((vf->canvas0Addr != 0)
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
&& ((DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) == 0)
/* check di_post_viu_link */
#endif
) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (vf->canvas0Addr != (u32)-1) {
canvas_copy(vf->canvas0Addr & 0xff,
disp_canvas_index[rdma_canvas_id][0]);
canvas_copy((vf->canvas0Addr >> 8) & 0xff,
disp_canvas_index[rdma_canvas_id][1]);
canvas_copy((vf->canvas0Addr >> 16) & 0xff,
disp_canvas_index[rdma_canvas_id][2]);
} else {
vframe_canvas_set(&vf->canvas0_config[0],
vf->plane_num,
&disp_canvas_index[rdma_canvas_id][0]);
}
if (is_mvc || process_3d_type) {
if (vf->canvas1Addr != (u32)-1) {
canvas_copy(vf->canvas1Addr & 0xff,
disp_canvas_index[rdma_canvas_id][3]);
canvas_copy((vf->canvas1Addr >> 8) & 0xff,
disp_canvas_index[rdma_canvas_id][4]);
canvas_copy((vf->canvas1Addr >> 16) & 0xff,
disp_canvas_index[rdma_canvas_id][5]);
} else {
vframe_canvas_set(&vf->canvas1_config[0],
vf->plane_num,
&disp_canvas_index[rdma_canvas_id][3]);
}
}
VSYNC_WR_MPEG_REG(
VD1_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][0]);
if (is_mvc)
VSYNC_WR_MPEG_REG(
VD2_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
if (cur_frame_par &&
(cur_frame_par->vpp_2pic_mode == 1)) {
VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[rdma_canvas_id][0]);
if (is_mvc)
VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[rdma_canvas_id][0]);
} else {
VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
if (is_mvc)
VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[rdma_canvas_id][0]);
}
if (cur_frame_par
&& (process_3d_type & MODE_3D_ENABLE)
&& (process_3d_type & MODE_3D_TO_2D_R)
&& (cur_frame_par->vpp_2pic_mode
== VPP_SELECT_PIC1)) {
VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
if (is_mvc) {
VSYNC_WR_MPEG_REG(
VD2_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
VSYNC_WR_MPEG_REG(
VD2_IF0_CANVAS1 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
}
}
next_rdma_canvas_id = rdma_canvas_id ? 0 : 1;
#else
canvas_copy(vf->canvas0Addr & 0xff, disp_canvas_index[0]);
canvas_copy((vf->canvas0Addr >> 8) & 0xff,
disp_canvas_index[1]);
canvas_copy((vf->canvas0Addr >> 16) & 0xff,
disp_canvas_index[2]);
if (is_mvc || process_3d_type) {
canvas_copy(vf->canvas1Addr & 0xff,
disp_canvas_index[3]);
canvas_copy((vf->canvas1Addr >> 8) & 0xff,
disp_canvas_index[4]);
canvas_copy((vf->canvas1Addr >> 16) & 0xff,
disp_canvas_index[5]);
}
VSYNC_WR_MPEG_REG(
VD1_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[0]);
if (is_mvc)
VSYNC_WR_MPEG_REG(
VD2_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[0]);
if (cur_frame_par &&
(cur_frame_par->vpp_2pic_mode == 1)) {
VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[0]);
if (is_mvc)
VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[0]);
} else {
VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[1]);
if (is_mvc)
VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 +
cur_dev->viu_off,
disp_canvas[1]);
}
#endif
}
/* set video PTS */
if (cur_dispbuf != vf) {
if (vf->pts != 0) {
amlog_mask(LOG_MASK_TIMESTAMP,
"vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n",
vf->pts, timestamp_pcrscr_get(),
READ_MPEG_REG(SCR_HIU));
timestamp_vpts_set(vf->pts);
} else if (cur_dispbuf) {
amlog_mask(LOG_MASK_TIMESTAMP,
"vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n",
timestamp_vpts_get() +
DUR2PTS(cur_dispbuf->duration),
timestamp_pcrscr_get(),
READ_MPEG_REG(SCR_HIU));
timestamp_vpts_inc(DUR2PTS
(cur_dispbuf->duration));
vpts_remainder +=
DUR2PTS_RM(cur_dispbuf->duration);
if (vpts_remainder >= 0xf) {
vpts_remainder -= 0xf;
timestamp_vpts_inc(-1);
}
}
vf->type_backup = vf->type;
}
if (cur_dispbuf &&
(cur_dispbuf->ratio_control &
DISP_RATIO_ADAPTED_PICMODE)) {
if (vf && (cur_dispbuf->ratio_control
== vf->ratio_control)
&& memcmp(&cur_dispbuf->pic_mode,
&vf->pic_mode,
sizeof(struct vframe_pic_mode_s)))
force_toggle = true;
else if (memcmp(&cur_dispbuf->pic_mode,
&gPic_info[0],
sizeof(struct vframe_pic_mode_s)))
force_toggle = true;
}
if ((last_process_3d_type != process_3d_type)
|| (last_el_status != vf_with_el))
force_toggle = true;
/* enable new config on the new frames */
if (first_picture || force_toggle ||
(cur_dispbuf &&
((cur_dispbuf->bufWidth != vf->bufWidth) ||
(cur_dispbuf->width != vf->width) ||
(cur_dispbuf->height != vf->height) ||
(cur_dispbuf->bitdepth != vf->bitdepth) ||
(cur_dispbuf->trans_fmt != vf->trans_fmt) ||
(cur_dispbuf->ratio_control != vf->ratio_control) ||
((cur_dispbuf->type_backup & VIDTYPE_INTERLACE) !=
(vf->type_backup & VIDTYPE_INTERLACE)) ||
(cur_dispbuf->type != vf->type)))) {
int iret;
last_process_3d_type = process_3d_type;
atomic_inc(&video_sizechange);
wake_up_interruptible(&amvideo_event_wait);
amlog_mask(LOG_MASK_FRAMEINFO,
"%s %dx%d ar=0x%x\n",
((vf->type & VIDTYPE_TYPEMASK) ==
VIDTYPE_INTERLACE_TOP) ? "interlace-top"
: ((vf->type & VIDTYPE_TYPEMASK)
== VIDTYPE_INTERLACE_BOTTOM)
? "interlace-bottom" : "progressive", vf->width,
vf->height, vf->ratio_control);
#ifdef TV_3D_FUNCTION_OPEN
amlog_mask(LOG_MASK_FRAMEINFO,
"%s trans_fmt=%u\n", __func__, vf->trans_fmt);
#endif
next_frame_par = (&frame_parms[0] == next_frame_par) ?
&frame_parms[1] : &frame_parms[0];
update_layer_info(0);
iret = vpp_set_filters(
&glayer_info[0], vf,
next_frame_par, vinfo,
(is_dolby_vision_on() &&
is_dolby_vision_stb_mode()), 1);
if (iret == VppFilter_Success_and_Changed)
video_property_changed = 1;
memcpy(&gPic_info[0], &vf->pic_mode,
sizeof(struct vframe_pic_mode_s));
/* apply new vpp settings */
frame_par_ready_to_set = 1;
if (((vf->width > 1920) && (vf->height > 1088)) ||
((vf->type & VIDTYPE_COMPRESS) &&
(vf->compWidth > 1920) &&
(vf->compHeight > 1080))) {
if (vpu_clk_level == 0) {
vpu_clk_level = 1;
spin_lock_irqsave(&lock, flags);
vpu_delay_work_flag |=
VPU_DELAYWORK_VPU_CLK;
spin_unlock_irqrestore(&lock, flags);
}
} else {
if (vpu_clk_level == 1) {
vpu_clk_level = 0;
spin_lock_irqsave(&lock, flags);
vpu_delay_work_flag |=
VPU_DELAYWORK_VPU_CLK;
spin_unlock_irqrestore(&lock, flags);
}
}
}
/* if el is unnecessary, afbc2 need to be closed */
if ((last_el_status == 1) && (vf_with_el == 0))
need_disable_vd2 = true;
if (((vf->type & VIDTYPE_MVC) == 0)
&& last_mvc_status)
need_disable_vd2 = true;
last_el_status = vf_with_el;
if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) &&
((!property_changed_true) || (vf != cur_dispbuf))) {
if (disable_video == VIDEO_DISABLE_FORNEXT) {
EnableVideoLayer();
disable_video = VIDEO_DISABLE_NONE;
}
if (first_picture && (disable_video != VIDEO_DISABLE_NORMAL)) {
EnableVideoLayer();
if ((vf->type & VIDTYPE_MVC) ||
(cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2)))
EnableVideoLayer2();
else if (cur_dispbuf2 &&
!(cur_dispbuf2->type & VIDTYPE_COMPRESS))
VD2_MEM_POWER_ON();
else if (vf_with_el)
EnableVideoLayer2();
else if (need_disable_vd2)
DisableVideoLayer2();
}
}
if (cur_dispbuf && (cur_dispbuf->type != vf->type)) {
if ((vf->type & VIDTYPE_MVC) ||
(cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2)))
EnableVideoLayer2();
else {
if (cur_dispbuf2 &&
!(cur_dispbuf2->type & VIDTYPE_COMPRESS))
VD2_MEM_POWER_ON();
else if (vf_with_el)
EnableVideoLayer2();
else if (need_disable_vd2)
DisableVideoLayer2();
}
}
cur_dispbuf = vf;
if (cur_dispbuf && (cur_dispbuf->type & VIDTYPE_MVC))
last_mvc_status = true;
else
last_mvc_status = false;
if (first_picture) {
frame_par_ready_to_set = 1;
first_frame_toggled = 1;
#ifdef VIDEO_PTS_CHASE
av_sync_flag = 0;
#endif
}
if (cur_dispbuf != &vf_local)
video_keeper_new_frame_notify();
if ((vf != &vf_local) && (vf) && !vsync_pts_aligned) {
#ifdef PTS_TRACE_DEBUG
pr_info("####timestamp_pcrscr_get() = 0x%x, vf->pts = 0x%x, vsync_pts_inc = %d\n",
timestamp_pcrscr_get(), vf->pts, vsync_pts_inc);
#endif
if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc))
&& ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) {
vsync_pts_align = vsync_pts_inc / 4 -
(timestamp_pcrscr_get() - vf->pts);
vsync_pts_aligned = true;
#ifdef PTS_TRACE_DEBUG
pts_trace_his_rd = 0;
pr_info("####vsync_pts_align set to %d\n",
vsync_pts_align);
#endif
}
}
if (stop_update)
frame_par_ready_to_set = 0;
ATRACE_COUNTER(__func__, 0);
}
static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
{
u32 r;
u32 vphase, vini_phase, vformatter;
u32 pat, loop;
static const u32 vpat[MAX_VSKIP_COUNT + 1] = {
0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
u32 u, v;
u32 type, bit_mode = 0;
bool is_mvc = false;
if (vf == NULL) {
pr_info("viu_set_dcu vf NULL, return\n");
return;
}
type = vf->type;
if (type & VIDTYPE_MVC)
is_mvc = true;
pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type);
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
if (frame_par->nocomp)
type &= ~VIDTYPE_COMPRESS;
if (type & VIDTYPE_COMPRESS) {
r = (3 << 24) |
(vpp_hold_line << 16) |
((legacy_vpp ? 1 : 2) << 14) | /* burst1 */
(vf->bitdepth & BITDEPTH_MASK);
if (frame_par->hscale_skip_count)
r |= 0x33;
if (frame_par->vscale_skip_count)
r |= 0xcc;
#ifdef TV_REVERSE
if (reverse)
r |= (1<<26) | (1<<27);
#endif
if (vf->bitdepth & BITDEPTH_SAVING_MODE)
r |= (1<<28); /* mem_saving_mode */
if (type & VIDTYPE_SCATTER)
r |= (1<<29);
VSYNC_WR_MPEG_REG(AFBC_MODE, r);
r = 0x1700;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (vf && (vf->source_type
!= VFRAME_SOURCE_TYPE_HDMI))
r |= (1 << 19); /* dos_uncomp */
if (type & VIDTYPE_COMB_MODE)
r |= (1 << 20);
}
VSYNC_WR_MPEG_REG(AFBC_ENABLE, r);
r = 0x100;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (type & VIDTYPE_VIU_444)
r |= 0;
else if (type & VIDTYPE_VIU_422)
r |= (1 << 12);
else
r |= (2 << 12);
}
VSYNC_WR_MPEG_REG(AFBC_CONV_CTRL, r);
u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3;
v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3;
VSYNC_WR_MPEG_REG(AFBC_DEC_DEF_COLOR,
0x3FF00000 | /*Y,bit20+*/
0x80 << (u + 10) |
0x80 << v);
/* chroma formatter */
r = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
r = HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_ALWAYS_RPT |
(0 << VFORMATTER_INIPHASE_BIT) |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
} else
#endif
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
r = HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xc << VFORMATTER_INIPHASE_BIT) |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
if (type & VIDTYPE_VIU_444) {
r &= ~HFORMATTER_EN;
r &= ~VFORMATTER_EN;
r &= ~HFORMATTER_YC_RATIO_2_1;
} else if (type & VIDTYPE_VIU_422) {
r &= ~VFORMATTER_EN;
}
} else {
r = HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xc << VFORMATTER_INIPHASE_BIT) |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
}
VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, r);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (type & VIDTYPE_COMPRESS_LOSS)
VSYNC_WR_MPEG_REG(
AFBCDEC_IQUANT_ENABLE,
((1 << 11) |
(1 << 10) |
(1 << 4) |
(1 << 0)));
else
VSYNC_WR_MPEG_REG(
AFBCDEC_IQUANT_ENABLE, 0);
}
vd1_path_select(true);
VSYNC_WR_MPEG_REG(
VD1_IF0_GEN_REG + cur_dev->viu_off, 0);
return;
} else {
if ((vf->bitdepth & BITDEPTH_Y10) &&
(!frame_par->nocomp)) {
if (vf->type & VIDTYPE_VIU_444) {
bit_mode = 2;
} else {
if (vf->bitdepth & FULL_PACK_422_MODE)
bit_mode = 3;
else
bit_mode = 1;
}
} else {
bit_mode = 0;
}
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG_BITS(
G12_VD1_IF0_GEN_REG3,
(bit_mode & 0x3), 8, 2);
if (is_mvc)
VSYNC_WR_MPEG_REG_BITS(
G12_VD2_IF0_GEN_REG3,
(bit_mode & 0x3), 8, 2);
} else {
VSYNC_WR_MPEG_REG_BITS(
VD1_IF0_GEN_REG3 +
cur_dev->viu_off,
(bit_mode & 0x3), 8, 2);
if (is_mvc)
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG3 +
cur_dev->viu_off,
(bit_mode & 0x3), 8, 2);
}
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
DI_POST_WR_REG_BITS(DI_IF1_GEN_REG3,
(bit_mode&0x3), 8, 2);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
DI_POST_WR_REG_BITS(DI_IF2_GEN_REG3,
(bit_mode & 0x3), 8, 2);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
DI_POST_WR_REG_BITS(DI_IF0_GEN_REG3,
(bit_mode & 0x3), 8, 2);
#endif
vd1_path_select(false);
VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0);
}
}
r = (3 << VDIF_URGENT_BIT) |
(vpp_hold_line << VDIF_HOLD_LINES_BIT) |
VDIF_FORMAT_SPLIT |
VDIF_CHRO_RPT_LAST | VDIF_ENABLE;
/* | VDIF_RESET_ON_GO_FIELD;*/
if (debug_flag & DEBUG_FLAG_GOFIELD_MANUL)
r |= 1<<7; /*for manul triggle gofiled.*/
if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0)
r |= VDIF_SEPARATE_EN;
else {
if (type & VIDTYPE_VIU_422)
r |= VDIF_FORMAT_422;
else {
r |= VDIF_FORMAT_RGB888_YUV444 |
VDIF_DEMUX_MODE_RGB_444;
}
}
if (frame_par->hscale_skip_count)
r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
/*enable go field reset default according to vlsi*/
r |= VDIF_RESET_ON_GO_FIELD;
VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + cur_dev->viu_off, r);
if (is_mvc)
VSYNC_WR_MPEG_REG(
VD2_IF0_GEN_REG + cur_dev->viu_off, r);
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) {
if (type & VIDTYPE_VIU_NV21) {
VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 +
cur_dev->viu_off, 1, 0, 1);
} else {
VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 +
cur_dev->viu_off, 0, 0, 1);
}
#ifdef TV_REVERSE
if (reverse) {
VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 +
cur_dev->viu_off), 0xf, 2, 4);
if (is_mvc)
VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 +
cur_dev->viu_off), 0xf, 2, 4);
} else {
VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 +
cur_dev->viu_off), 0, 2, 4);
if (is_mvc)
VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 +
cur_dev->viu_off), 0, 2, 4);
}
#endif
}
/* #endif */
/* chroma formatter */
if (type & VIDTYPE_VIU_444) {
VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_1_1);
if (is_mvc)
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_1_1);
} else if (type & VIDTYPE_VIU_FIELD) {
vini_phase = 0xc << VFORMATTER_INIPHASE_BIT;
vphase =
((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) <<
VFORMATTER_PHASE_BIT;
/*vlsi suggest only for yuv420 vformatter shold be 1*/
if (type & VIDTYPE_VIU_NV21)
vformatter = VFORMATTER_EN;
else
vformatter = 0;
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
VSYNC_WR_MPEG_REG(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
((type & VIDTYPE_VIU_422) ?
VFORMATTER_RPTLINE0_EN :
VFORMATTER_ALWAYS_RPT) |
(0 << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
((type & VIDTYPE_VIU_422) ?
0 :
VFORMATTER_EN));
pr_debug("\tvd1 set fmt(dovi tv)\n");
} else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
is_meson_txlx_cpu()) {
if ((vf->width >= 3840) &&
(vf->height >= 2160) &&
(type & VIDTYPE_VIU_422)) {
VSYNC_WR_MPEG_REG(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN | vini_phase | vphase);
if (is_mvc)
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_RRT_PIXEL0 |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase);
} else {
VSYNC_WR_MPEG_REG(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
(is_dolby_vision_on() ?
HFORMATTER_REPEAT : 0) |
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN | vini_phase | vphase |
vformatter);
if (is_mvc)
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase |
vformatter);
}
} else {
VSYNC_WR_MPEG_REG(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
(is_dolby_vision_on() ?
HFORMATTER_REPEAT : 0) |
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase |
vformatter);
if (is_mvc)
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase |
vformatter);
}
} else if (type & VIDTYPE_MVC) {
VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xe << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
if (is_mvc)
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN | (0xa <<
VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
} else if ((type & VIDTYPE_INTERLACE)
&& (((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))) {
VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN | (0xe <<
VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
if (is_mvc)
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xe << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
} else {
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
VSYNC_WR_MPEG_REG(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_ALWAYS_RPT |
(0 << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
} else {
VSYNC_WR_MPEG_REG(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
(is_dolby_vision_on() ?
HFORMATTER_REPEAT : 0) |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xa << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
}
if (is_mvc)
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xa << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if ((is_meson_txlx_cpu()
|| cpu_after_eq(
MESON_CPU_MAJOR_ID_G12A))
&& is_dolby_vision_on()
&& is_dolby_vision_stb_mode()
&& (vf->source_type ==
VFRAME_SOURCE_TYPE_OTHERS))
VSYNC_WR_MPEG_REG_BITS(
VIU_VD1_FMT_CTRL + cur_dev->viu_off,
1, 29, 1);
#endif
/* LOOP/SKIP pattern */
pat = vpat[frame_par->vscale_skip_count];
if (type & VIDTYPE_VIU_FIELD) {
loop = 0;
if (type & VIDTYPE_INTERLACE)
pat = vpat[frame_par->vscale_skip_count >> 1];
} else if (type & VIDTYPE_MVC) {
loop = 0x11;
if (is_need_framepacking_output()) {
pat = 0;
} else
pat = 0x80;
} else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) {
loop = 0x11;
pat <<= 4;
} else
loop = 0;
VSYNC_WR_MPEG_REG(
VD1_IF0_RPT_LOOP + cur_dev->viu_off,
(loop << VDIF_CHROMA_LOOP1_BIT) |
(loop << VDIF_LUMA_LOOP1_BIT) |
(loop << VDIF_CHROMA_LOOP0_BIT) |
(loop << VDIF_LUMA_LOOP0_BIT));
if (is_mvc)
VSYNC_WR_MPEG_REG(
VD2_IF0_RPT_LOOP + cur_dev->viu_off,
(loop << VDIF_CHROMA_LOOP1_BIT) |
(loop << VDIF_LUMA_LOOP1_BIT) |
(loop << VDIF_CHROMA_LOOP0_BIT) |
(loop << VDIF_LUMA_LOOP0_BIT));
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat);
if (type & VIDTYPE_MVC) {
if (is_need_framepacking_output())
pat = 0;
else
pat = 0x88;
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat);
}
/* picture 0/1 control */
if ((((type & VIDTYPE_INTERLACE) == 0) &&
((type & VIDTYPE_VIU_FIELD) == 0) &&
((type & VIDTYPE_MVC) == 0)) ||
(frame_par->vpp_2pic_mode & 0x3)) {
/* progressive frame in two pictures */
if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) {
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, (2 << 26) |
/* two pic mode */
(2 << 24) |
/* use own last line */
(1 << 8) |
/* toggle pic 0 and 1, use pic1 first*/
(0x01));
/* loop pattern */
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, (2 << 26) |
/* two pic mode */
(2 << 24) |
/* use own last line */
(1 << 8) |
/* toggle pic 0 and 1,use pic1 first */
(0x01));
/* loop pattern */
} else {
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, (2 << 26) |
/* two pic mode */
(2 << 24) |
/* use own last line */
(2 << 8) |
/* toggle pic 0 and 1, use pic0 first */
(0x01));
/* loop pattern */
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, (2 << 26) |
/* two pic mode */
(2 << 24) |
/* use own last line */
(2 << 8) |
/* toggle pic 0 and 1, use pic0 first */
(0x01));
/* loop pattern */
}
} else if (process_3d_type & MODE_3D_OUT_FA_MASK) {
/*FA LR/TB output , do nothing*/
} else {
if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) {
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
if (is_mvc) {
VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
}
} else {
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
if (is_mvc) {
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
}
}
}
}
static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
{
u32 r;
u32 vphase, vini_phase;
u32 pat, loop;
static const u32 vpat[MAX_VSKIP_COUNT + 1] = {
0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
u32 u, v;
u32 type, bit_mode = 0;
if (!vf) {
pr_err("vd2_set_dcu vf is NULL\n");
return;
}
type = vf->type;
pr_debug("set dcu for vd2 %p, type:0x%x\n", vf, type);
last_el_w = (vf->type
& VIDTYPE_COMPRESS) ?
vf->compWidth :
vf->width;
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
if (type & VIDTYPE_COMPRESS) {
r = (3 << 24) |
(vpp_hold_line << 16) |
((legacy_vpp ? 1 : 2) << 14) | /* burst1 */
(vf->bitdepth & BITDEPTH_MASK);
if (frame_par->hscale_skip_count)
r |= 0x33;
if (frame_par->vscale_skip_count)
r |= 0xcc;
#ifdef TV_REVERSE
if (reverse)
r |= (1<<26) | (1<<27);
#endif
if (vf->bitdepth & BITDEPTH_SAVING_MODE)
r |= (1<<28); /* mem_saving_mode */
if (type & VIDTYPE_SCATTER)
r |= (1<<29);
VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r);
r = 0x1700;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (vf && (vf->source_type
!= VFRAME_SOURCE_TYPE_HDMI))
r |= (1 << 19); /* dos_uncomp */
}
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, r);
r = 0x100;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (type & VIDTYPE_VIU_444)
r |= 0;
else if (type & VIDTYPE_VIU_422)
r |= (1 << 12);
else
r |= (2 << 12);
}
VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r);
u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3;
v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3;
VSYNC_WR_MPEG_REG(VD2_AFBC_DEC_DEF_COLOR,
0x3FF00000 | /*Y,bit20+*/
0x80 << (u + 10) |
0x80 << v);
/* chroma formatter */
r = HFORMATTER_EN |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
r |= HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_ALWAYS_RPT |
(0 << VFORMATTER_INIPHASE_BIT) |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
} else
#endif
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
r = HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
if (is_dolby_vision_on())
r |= HFORMATTER_REPEAT |
(0xc << VFORMATTER_INIPHASE_BIT);
else
r |= HFORMATTER_RRT_PIXEL0 |
(0 << VFORMATTER_INIPHASE_BIT);
if (type & VIDTYPE_VIU_444) {
r &= ~HFORMATTER_EN;
r &= ~VFORMATTER_EN;
r &= ~HFORMATTER_YC_RATIO_2_1;
} else if (type & VIDTYPE_VIU_422) {
r &= ~VFORMATTER_EN;
}
} else {
r = HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0x8 << VFORMATTER_PHASE_BIT) |
VFORMATTER_EN;
if (is_dolby_vision_on())
r |= HFORMATTER_REPEAT |
(0xc << VFORMATTER_INIPHASE_BIT);
else
r |= HFORMATTER_RRT_PIXEL0 |
(0 << VFORMATTER_INIPHASE_BIT);
}
VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (type & VIDTYPE_COMPRESS_LOSS)
VSYNC_WR_MPEG_REG(
VD2_AFBCDEC_IQUANT_ENABLE,
((1 << 11) |
(1 << 10) |
(1 << 4) |
(1 << 0)));
else
VSYNC_WR_MPEG_REG(
VD2_AFBCDEC_IQUANT_ENABLE, 0);
}
vd2_path_select(true);
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG +
cur_dev->viu_off, 0);
return;
} else {
if ((vf->bitdepth & BITDEPTH_Y10) &&
(!frame_par->nocomp)) {
if (vf->type & VIDTYPE_VIU_444) {
bit_mode = 2;
} else {
if (vf->bitdepth & FULL_PACK_422_MODE)
bit_mode = 3;
else
bit_mode = 1;
}
} else {
bit_mode = 0;
}
vd2_path_select(false);
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG_BITS(
G12_VD2_IF0_GEN_REG3,
(bit_mode & 0x3), 8, 2);
} else {
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG3 + cur_dev->viu_off,
(bit_mode&0x3), 8, 2);
}
if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1))
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
if (type & VIDTYPE_VIU_NV21)
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG2 +
cur_dev->viu_off, 1, 0, 1);
else
VSYNC_WR_MPEG_REG_BITS(
VD2_IF0_GEN_REG2 +
cur_dev->viu_off, 0, 0, 1);
}
}
r = (3 << VDIF_URGENT_BIT) |
(vpp_hold_line << VDIF_HOLD_LINES_BIT) |
VDIF_FORMAT_SPLIT |
VDIF_CHRO_RPT_LAST | VDIF_ENABLE;
/* | VDIF_RESET_ON_GO_FIELD;*/
if (debug_flag & DEBUG_FLAG_GOFIELD_MANUL)
r |= 1<<7; /*for manul triggle gofiled.*/
if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0)
r |= VDIF_SEPARATE_EN;
else {
if (type & VIDTYPE_VIU_422)
r |= VDIF_FORMAT_422;
else {
r |= VDIF_FORMAT_RGB888_YUV444 |
VDIF_DEMUX_MODE_RGB_444;
}
}
if (frame_par->hscale_skip_count)
r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, r);
#ifdef TV_REVERSE
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) {
if (reverse) {
VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 +
cur_dev->viu_off), 0xf, 2, 4);
} else {
VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 +
cur_dev->viu_off), 0, 2, 4);
}
}
#endif
/* chroma formatter */
if (type & VIDTYPE_VIU_444) {
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_1_1);
} else if (type & VIDTYPE_VIU_FIELD) {
vini_phase = 0xc << VFORMATTER_INIPHASE_BIT;
vphase =
((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) <<
VFORMATTER_PHASE_BIT;
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_ALWAYS_RPT |
(0 << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
pr_debug("\tvd2 set fmt(dovi tv)\n");
} else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
is_meson_txlx_cpu()) {
if ((vf->width >= 3840) &&
(vf->height >= 2160) &&
(type & VIDTYPE_VIU_422)) {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_RRT_PIXEL0 |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN | VFORMATTER_RPTLINE0_EN |
vini_phase | vphase);
} else {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
(is_dolby_vision_on() ?
HFORMATTER_REPEAT : 0) |
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
vini_phase | vphase |
VFORMATTER_EN);
}
} else {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
(is_dolby_vision_on() ?
HFORMATTER_REPEAT : 0) |
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN | vini_phase | vphase |
VFORMATTER_EN);
}
} else if (type & VIDTYPE_MVC) {
VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xe << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN | (0xa <<
VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
} else if ((type & VIDTYPE_INTERLACE)
&&
(((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))) {
VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xe << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
} else {
if (is_meson_txlx_package_962X()
&& !is_dolby_vision_stb_mode()
&& is_dolby_vision_on()) {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
HFORMATTER_REPEAT |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_ALWAYS_RPT |
(0 << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
pr_info("\tvd2 set fmt(dovi tv)\n");
} else {
VSYNC_WR_MPEG_REG(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
(is_dolby_vision_on() ?
HFORMATTER_REPEAT : 0) |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
(0xc << VFORMATTER_INIPHASE_BIT) |
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) | VFORMATTER_EN);
pr_info("\tvd2 set fmt(dovi:%d)\n",
/*is_dolby_vision_on()*/0);
}
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if ((is_meson_txlx_cpu()
|| cpu_after_eq(
MESON_CPU_MAJOR_ID_G12A))
&& is_dolby_vision_on()
&& is_dolby_vision_stb_mode()
&& (vf->source_type ==
VFRAME_SOURCE_TYPE_OTHERS))
VSYNC_WR_MPEG_REG_BITS(
VIU_VD2_FMT_CTRL + cur_dev->viu_off,
1, 29, 1);
#endif
/* LOOP/SKIP pattern */
pat = vpat[frame_par->vscale_skip_count];
if (type & VIDTYPE_VIU_FIELD) {
loop = 0;
if (type & VIDTYPE_INTERLACE)
pat = vpat[frame_par->vscale_skip_count >> 1];
} else if (type & VIDTYPE_MVC) {
loop = 0x11;
pat = 0x80;
} else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) {
loop = 0x11;
pat <<= 4;
} else
loop = 0;
VSYNC_WR_MPEG_REG(
VD2_IF0_RPT_LOOP + cur_dev->viu_off,
(loop << VDIF_CHROMA_LOOP1_BIT) |
(loop << VDIF_LUMA_LOOP1_BIT) |
(loop << VDIF_CHROMA_LOOP0_BIT) |
(loop << VDIF_LUMA_LOOP0_BIT));
if (type & VIDTYPE_MVC)
pat = 0x88;
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat);
if (platform_type == 0) {
/* picture 0/1 control */
if (((type & VIDTYPE_INTERLACE) == 0) &&
((type & VIDTYPE_VIU_FIELD) == 0) &&
((type & VIDTYPE_MVC) == 0)) {
/* progressive frame in two pictures */
} else {
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0);
}
} else {
/* picture 0/1 control */
if ((((type & VIDTYPE_INTERLACE) == 0) &&
((type & VIDTYPE_VIU_FIELD) == 0) &&
((type & VIDTYPE_MVC) == 0)) ||
(next_frame_par->vpp_2pic_mode & 0x3)) {
/* progressive frame in two pictures */
} else {
if (next_frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) {
VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
} else {
VSYNC_WR_MPEG_REG(
VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(
VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
}
}
}
}
static int detect_vout_type(void)
{
int vout_type = VOUT_TYPE_PROG;
if ((vinfo) && (vinfo->field_height != vinfo->height)) {
if ((vinfo->height == 576) || (vinfo->height == 480))
vout_type = (READ_VCBUS_REG(ENCI_INFO_READ) &
(1 << 29)) ?
VOUT_TYPE_BOT_FIELD : VOUT_TYPE_TOP_FIELD;
else if (vinfo->height == 1080)
vout_type = (((READ_VCBUS_REG(ENCP_INFO_READ) >> 16) &
0x1fff) < 562) ?
VOUT_TYPE_TOP_FIELD : VOUT_TYPE_BOT_FIELD;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_vsync_rdma_enable()) {
if (vout_type == VOUT_TYPE_TOP_FIELD)
vout_type = VOUT_TYPE_BOT_FIELD;
else if (vout_type == VOUT_TYPE_BOT_FIELD)
vout_type = VOUT_TYPE_TOP_FIELD;
}
#endif
}
return vout_type;
}
#ifdef INTERLACE_FIELD_MATCH_PROCESS
static inline bool interlace_field_type_need_match(int vout_type,
struct vframe_s *vf)
{
if (DUR2PTS(vf->duration) != vsync_pts_inc)
return false;
if ((vout_type == VOUT_TYPE_TOP_FIELD) &&
((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_BOTTOM))
return true;
else if ((vout_type == VOUT_TYPE_BOT_FIELD) &&
((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))
return true;
return false;
}
#endif
static int calc_hold_line(void)
{
if ((READ_VCBUS_REG(ENCI_VIDEO_EN) & 1) == 0)
return READ_VCBUS_REG(ENCP_VIDEO_VAVON_BLINE) >> 1;
else
return READ_VCBUS_REG(ENCP_VFIFO2VD_LINE_TOP_START) >> 1;
}
/* add a new function to check if current display frame has been*/
/*displayed for its duration */
static inline bool duration_expire(struct vframe_s *cur_vf,
struct vframe_s *next_vf, u32 dur)
{
u32 pts;
s32 dur_disp;
static s32 rpt_tab_idx;
static const u32 rpt_tab[4] = { 0x100, 0x100, 0x300, 0x300 };
/* do not switch to new frames in none-normal speed */
if (vsync_slow_factor > 1000)
return false;
if ((cur_vf == NULL) || (cur_dispbuf == &vf_local))
return true;
pts = next_vf->pts;
if (pts == 0)
dur_disp = DUR2PTS(cur_vf->duration);
else
dur_disp = pts - timestamp_vpts_get();
if ((dur << 8) >= (dur_disp * rpt_tab[rpt_tab_idx & 3])) {
rpt_tab_idx = (rpt_tab_idx + 1) & 3;
return true;
} else
return false;
}
#define VPTS_RESET_THRO
#ifdef PTS_LOGGING
static inline void vpts_perform_pulldown(struct vframe_s *next_vf,
bool *expired)
{
int pattern_range, expected_curr_interval;
int expected_prev_interval;
int next_vf_nextpts = 0;
/* Dont do anything if we have invalid data */
if (!next_vf || !next_vf->pts)
return;
if (next_vf->next_vf_pts_valid)
next_vf_nextpts = next_vf->next_vf_pts;
switch (pts_pattern_detected) {
case PTS_32_PATTERN:
pattern_range = PTS_32_PATTERN_DETECT_RANGE;
switch (pre_pts_trace) {
case 3:
expected_prev_interval = 3;
expected_curr_interval = 2;
break;
case 2:
expected_prev_interval = 2;
expected_curr_interval = 3;
break;
default:
return;
}
if (!next_vf_nextpts)
next_vf_nextpts = next_vf->pts +
PTS_32_PATTERN_DURATION;
break;
case PTS_22_PATTERN:
if (pre_pts_trace != 2)
return;
pattern_range = PTS_22_PATTERN_DETECT_RANGE;
expected_prev_interval = 2;
expected_curr_interval = 2;
if (!next_vf_nextpts)
next_vf_nextpts = next_vf->pts +
PTS_22_PATTERN_DURATION;
break;
case PTS_41_PATTERN:
/* TODO */
default:
return;
}
/* We do nothing if we dont have enough data*/
if (pts_pattern[pts_pattern_detected] != pattern_range)
return;
if (*expired) {
if (pts_trace < expected_curr_interval) {
/* 2323232323..2233..2323, prev=2, curr=3,*/
/* check if next frame will toggle after 3 vsyncs */
/* 22222...22222 -> 222..2213(2)22...22 */
/* check if next frame will toggle after 3 vsyncs */
int nextPts = timestamp_pcrscr_get() + vsync_pts_align;
if (/*((int)(nextPts + expected_prev_interval * */
/*vsync_pts_inc - next_vf->next_vf_pts) < 0) && */
((int)(nextPts + (expected_prev_interval + 1) *
vsync_pts_inc - next_vf_nextpts) >= 0)) {
*expired = false;
if (pts_log_enable[PTS_32_PATTERN]
|| pts_log_enable[PTS_22_PATTERN])
pr_info("hold frame for pattern: %d",
pts_pattern_detected);
}
/* here need to escape a vsync */
if (timestamp_pcrscr_get() >
(next_vf->pts + vsync_pts_inc)) {
*expired = true;
pts_escape_vsync = 1;
if (pts_log_enable[PTS_32_PATTERN]
|| pts_log_enable[PTS_22_PATTERN])
pr_info("escape a vsync pattern: %d",
pts_pattern_detected);
}
}
} else {
if (pts_trace == expected_curr_interval) {
/* 23232323..233223...2323 curr=2, prev=3 */
/* check if this frame will expire next vsyncs and */
/* next frame will expire after 3 vsyncs */
/* 22222...22222 -> 222..223122...22 */
/* check if this frame will expire next vsyncs and */
/* next frame will expire after 2 vsyncs */
int nextPts = timestamp_pcrscr_get() + vsync_pts_align;
if (((int)(nextPts + vsync_pts_inc - next_vf->pts)
>= 0) &&
((int)(nextPts +
vsync_pts_inc * (expected_prev_interval - 1)
- next_vf_nextpts) < 0) &&
((int)(nextPts + expected_prev_interval *
vsync_pts_inc - next_vf_nextpts) >= 0)) {
*expired = true;
if (pts_log_enable[PTS_32_PATTERN]
|| pts_log_enable[PTS_22_PATTERN])
pr_info("pull frame for pattern: %d",
pts_pattern_detected);
}
}
}
}
#endif
static inline bool vpts_expire(struct vframe_s *cur_vf,
struct vframe_s *next_vf,
int toggled_cnt)
{
u32 pts;
#ifdef VIDEO_PTS_CHASE
u32 vid_pts, scr_pts;
#endif
u32 systime;
u32 adjust_pts, org_vpts;
bool expired;
if (next_vf == NULL)
return false;
if (videopeek) {
videopeek = false;
pr_info("video peek toogle the first frame\n");
return true;
}
if (debug_flag & DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC)
return true;
if (/*(cur_vf == NULL) || (cur_dispbuf == &vf_local) ||*/ debugflags &
DEBUG_FLAG_FFPLAY)
return true;
if ((freerun_mode == FREERUN_NODUR) || hdmi_in_onvideo)
return true;
/*freerun for game mode*/
if (next_vf->flag & VFRAME_FLAG_GAME_MODE)
return true;
if (step_enable) {
if (step_flag)
return false;
if (!step_flag) {
step_flag = 1;
return true;
}
}
if ((trickmode_i == 1) || ((trickmode_fffb == 1))) {
if (((atomic_read(&trickmode_framedone) == 0)
|| (trickmode_i == 1)) && (!to_notify_trick_wait)
&& (trickmode_duration_count <= 0)) {
#if 0
if (cur_vf)
pts = timestamp_vpts_get() +
trickmode_duration;
else
return true;
#else
return true;
#endif
} else
return false;
}
if (omx_secret_mode && (!omx_run || !omx_drop_done))
return false;
if (next_vf->duration == 0)
return true;
systime = timestamp_pcrscr_get();
pts = next_vf->pts;
if (((pts == 0) && (cur_dispbuf != &vf_local))
|| (freerun_mode == FREERUN_DUR)) {
pts =
timestamp_vpts_get() +
(cur_vf ? DUR2PTS(cur_vf->duration) : 0);
}
/* check video PTS discontinuity */
else if ((enable_video_discontinue_report) &&
(first_frame_toggled) &&
(abs(systime - pts) > tsync_vpts_discontinuity_margin()) &&
((next_vf->flag & VFRAME_FLAG_NO_DISCONTINUE) == 0)) {
/*
* if paused ignore discontinue
*/
if (!timestamp_pcrscr_enable_state()) {
/*pr_info("video pts discontinue,
* but pcrscr is disabled,
* return false\n");
*/
return false;
}
pts =
timestamp_vpts_get() +
(cur_vf ? DUR2PTS(cur_vf->duration) : 0);
/* pr_info("system=0x%x vpts=0x%x\n", systime,*/
/*timestamp_vpts_get()); */
if ((int)(systime - pts) >= 0) {
if (next_vf->pts != 0)
tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY,
next_vf->pts);
else if (next_vf->pts == 0 &&
(tsync_get_mode() != TSYNC_MODE_PCRMASTER))
tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY,
pts);
/* pr_info("discontinue,
* systime=0x%x vpts=0x%x next_vf->pts = 0x%x\n",
* systime,
* pts,
* next_vf->pts);
*/
/* pts==0 is a keep frame maybe. */
if (systime > next_vf->pts || next_vf->pts == 0)
return true;
if (omx_secret_mode == true)
return true;
return false;
} else if (omx_secret_mode == true)
return true;
} else if (omx_run
&& omx_secret_mode
&& (omx_pts + omx_pts_interval_upper < next_vf->pts)
&& (abs(omx_pts_set_index - next_vf->omx_index) <= 16)
&& (omx_pts_set_index >= next_vf->omx_index)) {
pr_info("omx, omx_pts=%d omx_pts_set_index=%d pts=%d omx_index=%d\n",
omx_pts,
omx_pts_set_index,
next_vf->pts,
next_vf->omx_index);
return true;
}
#if 1
if (vsync_pts_inc_upint && (!freerun_mode)) {
struct vframe_states frame_states;
u32 delayed_ms, t1, t2;
delayed_ms =
calculation_stream_delayed_ms(PTS_TYPE_VIDEO, &t1, &t2);
if (video_vf_get_states(&frame_states) == 0) {
u32 pcr = timestamp_pcrscr_get();
u32 vpts = timestamp_vpts_get();
u32 diff = pcr - vpts;
if (delayed_ms > 200) {
vsync_freerun++;
if (pcr < next_vf->pts
|| pcr < vpts + next_vf->duration) {
if (next_vf->pts > 0) {
timestamp_pcrscr_set
(next_vf->pts);
} else {
timestamp_pcrscr_set(vpts +
next_vf->duration);
}
}
return true;
} else if ((frame_states.buf_avail_num >= 3)
&& diff < vsync_pts_inc << 2) {
vsync_pts_inc_adj =
vsync_pts_inc + (vsync_pts_inc >> 2);
vsync_pts_125++;
} else if ((frame_states.buf_avail_num >= 2
&& diff < vsync_pts_inc << 1)) {
vsync_pts_inc_adj =
vsync_pts_inc + (vsync_pts_inc >> 3);
vsync_pts_112++;
} else if (frame_states.buf_avail_num >= 1
&& diff < vsync_pts_inc - 20) {
vsync_pts_inc_adj = vsync_pts_inc + 10;
vsync_pts_101++;
} else {
vsync_pts_inc_adj = 0;
vsync_pts_100++;
}
}
}
#endif
#ifdef VIDEO_PTS_CHASE
vid_pts = timestamp_vpts_get();
scr_pts = timestamp_pcrscr_get();
vid_pts += vsync_pts_inc;
if (av_sync_flag) {
if (vpts_chase) {
if ((abs(vid_pts - scr_pts) < 6000)
|| (abs(vid_pts - scr_pts) > 90000)) {
vpts_chase = 0;
pr_info("leave vpts chase mode, diff:%d\n",
vid_pts - scr_pts);
}
} else if ((abs(vid_pts - scr_pts) > 9000)
&& (abs(vid_pts - scr_pts) < 90000)) {
vpts_chase = 1;
if (vid_pts < scr_pts)
vpts_chase_pts_diff = 50;
else
vpts_chase_pts_diff = -50;
vpts_chase_counter =
((int)(scr_pts - vid_pts)) / vpts_chase_pts_diff;
pr_info("enter vpts chase mode, diff:%d\n",
vid_pts - scr_pts);
} else if (abs(vid_pts - scr_pts) >= 90000) {
pr_info("video pts discontinue, diff:%d\n",
vid_pts - scr_pts);
}
} else
vpts_chase = 0;
if (vpts_chase) {
u32 curr_pts =
scr_pts - vpts_chase_pts_diff * vpts_chase_counter;
/* pr_info("vchase pts %d, %d, %d, %d, %d\n",*/
/*curr_pts, scr_pts, curr_pts-scr_pts, vid_pts, vpts_chase_counter); */
return ((int)(curr_pts - pts)) >= 0;
} else {
int aud_start = (timestamp_apts_get() != -1);
if (!av_sync_flag && aud_start && (abs(scr_pts - pts) < 9000)
&& ((int)(scr_pts - pts) < 0)) {
av_sync_flag = 1;
pr_info("av sync ok\n");
}
return ((int)(scr_pts - pts)) >= 0;
}
#else
if (smooth_sync_enable) {
org_vpts = timestamp_vpts_get();
if ((abs(org_vpts + vsync_pts_inc - systime) <
M_PTS_SMOOTH_MAX)
&& (abs(org_vpts + vsync_pts_inc - systime) >
M_PTS_SMOOTH_MIN)) {
if (!video_frame_repeat_count) {
vpts_ref = org_vpts;
video_frame_repeat_count++;
}
if ((int)(org_vpts + vsync_pts_inc - systime) > 0) {
adjust_pts =
vpts_ref + (vsync_pts_inc -
M_PTS_SMOOTH_ADJUST) *
video_frame_repeat_count;
} else {
adjust_pts =
vpts_ref + (vsync_pts_inc +
M_PTS_SMOOTH_ADJUST) *
video_frame_repeat_count;
}
return (int)(adjust_pts - pts) >= 0;
}
if (video_frame_repeat_count) {
vpts_ref = 0;
video_frame_repeat_count = 0;
}
}
expired = (int)(timestamp_pcrscr_get() + vsync_pts_align - pts) >= 0;
#ifdef PTS_THROTTLE
if (expired && next_vf && next_vf->next_vf_pts_valid &&
(vsync_slow_factor == 1) &&
next_vf->next_vf_pts &&
(toggled_cnt > 0) &&
((int)(timestamp_pcrscr_get() + vsync_pts_inc +
vsync_pts_align - next_vf->next_vf_pts) < 0)) {
expired = false;
} else if (!expired && next_vf && next_vf->next_vf_pts_valid &&
(vsync_slow_factor == 1) &&
next_vf->next_vf_pts &&
(toggled_cnt == 0) &&
((int)(timestamp_pcrscr_get() + vsync_pts_inc +
vsync_pts_align - next_vf->next_vf_pts) >= 0)) {
expired = true;
}
#endif
#ifdef PTS_LOGGING
if (pts_enforce_pulldown) {
/* Perform Pulldown if needed*/
vpts_perform_pulldown(next_vf, &expired);
}
#endif
return expired;
#endif
}
static void vsync_notify(void)
{
if (video_notify_flag & VIDEO_NOTIFY_TRICK_WAIT) {
wake_up_interruptible(&amvideo_trick_wait);
video_notify_flag &= ~VIDEO_NOTIFY_TRICK_WAIT;
}
if (video_notify_flag & VIDEO_NOTIFY_FRAME_WAIT) {
video_notify_flag &= ~VIDEO_NOTIFY_FRAME_WAIT;
vf_notify_provider(RECEIVER_NAME,
VFRAME_EVENT_RECEIVER_FRAME_WAIT, NULL);
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (video_notify_flag & VIDEO_NOTIFY_POS_CHANGED) {
video_notify_flag &= ~VIDEO_NOTIFY_POS_CHANGED;
vf_notify_provider(RECEIVER_NAME,
VFRAME_EVENT_RECEIVER_POS_CHANGED, NULL);
}
#endif
if (video_notify_flag &
(VIDEO_NOTIFY_PROVIDER_GET | VIDEO_NOTIFY_PROVIDER_PUT)) {
int event = 0;
if (video_notify_flag & VIDEO_NOTIFY_PROVIDER_GET)
event |= VFRAME_EVENT_RECEIVER_GET;
if (video_notify_flag & VIDEO_NOTIFY_PROVIDER_PUT)
event |= VFRAME_EVENT_RECEIVER_PUT;
vf_notify_provider(RECEIVER_NAME, event, NULL);
video_notify_flag &=
~(VIDEO_NOTIFY_PROVIDER_GET | VIDEO_NOTIFY_PROVIDER_PUT);
}
#ifdef CONFIG_CLK81_DFS
check_and_set_clk81();
#endif
#ifdef CONFIG_GAMMA_PROC
gamma_adjust();
#endif
}
#ifdef FIQ_VSYNC
static irqreturn_t vsync_bridge_isr(int irq, void *dev_id)
{
vsync_notify();
return IRQ_HANDLED;
}
#endif
int get_vsync_count(unsigned char reset)
{
if (reset)
vsync_count = 0;
return vsync_count;
}
EXPORT_SYMBOL(get_vsync_count);
int get_vsync_pts_inc_mode(void)
{
return vsync_pts_inc_upint;
}
EXPORT_SYMBOL(get_vsync_pts_inc_mode);
void set_vsync_pts_inc_mode(int inc)
{
vsync_pts_inc_upint = inc;
}
EXPORT_SYMBOL(set_vsync_pts_inc_mode);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
void vsync_rdma_process(void)
{
vsync_rdma_config();
}
#endif
/* #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 */
static enum vmode_e old_vmode = VMODE_MAX;
/* #endif */
static enum vmode_e new_vmode = VMODE_MAX;
static inline bool video_vf_disp_mode_check(struct vframe_s *vf)
{
struct provider_disp_mode_req_s req;
int ret = -1;
req.vf = vf;
req.disp_mode = 0;
req.req_mode = 1;
if (is_dolby_vision_enable()) {
ret = vf_notify_provider_by_name("dv_vdin",
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
if (ret == -1)
vf_notify_provider_by_name("vdin0",
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
} else
vf_notify_provider_by_name("vdin0",
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
if (req.disp_mode == VFRAME_DISP_MODE_OK)
return false;
/*whether need to check pts??*/
video_vf_put(vf);
return true;
}
static enum vframe_disp_mode_e video_vf_disp_mode_get(struct vframe_s *vf)
{
struct provider_disp_mode_req_s req;
int ret = -1;
req.vf = vf;
req.disp_mode = 0;
req.req_mode = 0;
if (is_dolby_vision_enable()) {
ret = vf_notify_provider_by_name("dv_vdin",
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
if (ret == -1)
vf_notify_provider_by_name("vdin0",
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
} else
vf_notify_provider_by_name("vdin0",
VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req);
return req.disp_mode;
}
static inline bool video_vf_dirty_put(struct vframe_s *vf)
{
if (!vf->frame_dirty)
return false;
if (cur_dispbuf != vf) {
if (vf->pts != 0) {
amlog_mask(LOG_MASK_TIMESTAMP,
"vpts to vf->pts:0x%x,scr:0x%x,abs_scr: 0x%x\n",
vf->pts, timestamp_pcrscr_get(),
READ_MPEG_REG(SCR_HIU));
timestamp_vpts_set(vf->pts);
} else if (cur_dispbuf) {
amlog_mask(LOG_MASK_TIMESTAMP,
"vpts inc:0x%x,scr: 0x%x, abs_scr: 0x%x\n",
timestamp_vpts_get() +
DUR2PTS(cur_dispbuf->duration),
timestamp_pcrscr_get(),
READ_MPEG_REG(SCR_HIU));
timestamp_vpts_inc(
DUR2PTS(cur_dispbuf->duration));
vpts_remainder +=
DUR2PTS_RM(cur_dispbuf->duration);
if (vpts_remainder >= 0xf) {
vpts_remainder -= 0xf;
timestamp_vpts_inc(-1);
}
}
}
video_vf_put(vf);
return true;
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf)
{
struct vframe_s *toggle_vf = NULL;
int width_bl, width_el;
int height_bl, height_el;
int ret = dolby_vision_update_metadata(vf);
cur_dispbuf2 = dolby_vision_vf_peek_el(vf);
if (cur_dispbuf2) {
if (cur_dispbuf2->type & VIDTYPE_COMPRESS) {
VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR,
cur_dispbuf2->compHeadAddr>>4);
VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR,
cur_dispbuf2->compBodyAddr>>4);
} else {
vframe_canvas_set(&cur_dispbuf2->canvas0_config[0],
cur_dispbuf2->plane_num,
&disp_canvas_index[rdma_canvas_id][3]);
VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off,
disp_canvas[rdma_canvas_id][1]);
}
width_el = (cur_dispbuf2->type
& VIDTYPE_COMPRESS) ?
cur_dispbuf2->compWidth :
cur_dispbuf2->width;
if (!(cur_dispbuf2->type & VIDTYPE_VD2)) {
width_bl = (vf->type
& VIDTYPE_COMPRESS) ?
vf->compWidth :
vf->width;
if (width_el >= width_bl)
width_el = width_bl;
else if (width_el != width_bl / 2)
width_el = width_bl / 2;
}
ori2_start_x_lines = 0;
ori2_end_x_lines =
width_el - 1;
height_el = (cur_dispbuf2->type
& VIDTYPE_COMPRESS) ?
cur_dispbuf2->compHeight :
cur_dispbuf2->height;
if (!(cur_dispbuf2->type & VIDTYPE_VD2)) {
height_bl = (vf->type
& VIDTYPE_COMPRESS) ?
vf->compHeight :
vf->height;
if (height_el >= height_bl)
height_el = height_bl;
else if (height_el != height_bl / 2)
height_el = height_bl / 2;
}
ori2_start_y_lines = 0;
ori2_end_y_lines =
height_el - 1;
}
if (ret == 0) {
/* setting generated for this frame */
/* or DOVI in bypass mode */
toggle_vf = vf;
dolby_vision_set_toggle_flag(1);
} else {
/* fail generating setting for this frame */
toggle_vf = NULL;
dolby_vision_set_toggle_flag(0);
}
return toggle_vf;
}
static int dolby_vision_need_wait(void)
{
struct vframe_s *vf;
vf = video_vf_peek();
if (!vf || (dolby_vision_wait_metadata(vf) == 1))
return 1;
return 0;
}
#endif
/* patch for 4k2k bandwidth issue, skiw mali and vpu mif */
static void dmc_adjust_for_mali_vpu(unsigned int width,
unsigned int height, bool force_adjust)
{
if (toggle_count == last_toggle_count)
toggle_same_count++;
else {
last_toggle_count = toggle_count;
toggle_same_count = 0;
}
/*avoid 3840x2160 crop*/
if ((width >= 2000) && (height >= 1400) &&
(((dmc_config_state != 1) && (toggle_same_count < 30))
|| force_adjust)) {
if (0) {/* if (is_dolby_vision_enable()) { */
/* vpu dmc */
WRITE_DMCREG(
DMC_AM0_CHAN_CTRL,
0x85f403f4);
WRITE_DMCREG(
DMC_AM1_CHAN_CTRL,
0x85f403f4);
WRITE_DMCREG(
DMC_AM2_CHAN_CTRL,
0x85f403f4);
/* mali dmc */
WRITE_DMCREG(
DMC_AXI1_CHAN_CTRL,
0xff10ff4);
WRITE_DMCREG(
DMC_AXI2_CHAN_CTRL,
0xff10ff4);
WRITE_DMCREG(
DMC_AXI1_HOLD_CTRL,
0x08040804);
WRITE_DMCREG(
DMC_AXI2_HOLD_CTRL,
0x08040804);
} else {
/* vpu dmc */
WRITE_DMCREG(
DMC_AM1_CHAN_CTRL,
0x43028);
WRITE_DMCREG(
DMC_AM1_HOLD_CTRL,
0x18101818);
WRITE_DMCREG(
DMC_AM3_CHAN_CTRL,
0x85f403f4);
WRITE_DMCREG(
DMC_AM4_CHAN_CTRL,
0x85f403f4);
/* mali dmc */
WRITE_DMCREG(
DMC_AXI1_HOLD_CTRL,
0x10080804);
WRITE_DMCREG(
DMC_AXI2_HOLD_CTRL,
0x10080804);
}
dmc_config_state = 1;
} else if (((toggle_same_count >= 30) ||
((width < 2000) && (height < 1400))) &&
(dmc_config_state != 2)) {
/* vpu dmc */
WRITE_DMCREG(
DMC_AM0_CHAN_CTRL,
0x8FF003C4);
WRITE_DMCREG(
DMC_AM1_CHAN_CTRL,
0x3028);
WRITE_DMCREG(
DMC_AM1_HOLD_CTRL,
0x18101810);
WRITE_DMCREG(
DMC_AM2_CHAN_CTRL,
0x8FF003C4);
WRITE_DMCREG(
DMC_AM2_HOLD_CTRL,
0x3028);
WRITE_DMCREG(
DMC_AM3_CHAN_CTRL,
0x85f003f4);
WRITE_DMCREG(
DMC_AM4_CHAN_CTRL,
0x85f003f4);
/* mali dmc */
WRITE_DMCREG(
DMC_AXI1_CHAN_CTRL,
0x8FF00FF4);
WRITE_DMCREG(
DMC_AXI2_CHAN_CTRL,
0x8FF00FF4);
WRITE_DMCREG(
DMC_AXI1_HOLD_CTRL,
0x18101810);
WRITE_DMCREG(
DMC_AXI2_HOLD_CTRL,
0x18101810);
toggle_same_count = 30;
dmc_config_state = 2;
}
}
static bool is_sc_enable_before_pps(struct vpp_frame_par_s *par)
{
bool ret = false;
if (par) {
if (par->supsc0_enable &&
((par->supscl_path == CORE0_PPS_CORE1)
|| (par->supscl_path == CORE0_BEFORE_PPS)))
ret = true;
else if (par->supsc1_enable &&
(par->supscl_path == CORE1_BEFORE_PPS))
ret = true;
else if ((par->supsc0_enable || par->supsc1_enable)
&& (par->supscl_path == CORE0_CORE1_PPS))
ret = true;
}
return ret;
}
void correct_vd1_mif_size_for_DV(struct vpp_frame_par_s *par)
{
u32 aligned_mask = 0xfffffffe;
u32 old_len;
if ((is_dolby_vision_on() == true)
&& (par->VPP_line_in_length_ > 0)
&& !is_sc_enable_before_pps(par)) {
/* work around to skip the size check when sc enable */
if (cur_dispbuf2) {
/*
*if (cur_dispbuf2->type
* & VIDTYPE_COMPRESS)
* aligned_mask = 0xffffffc0;
*else
*/
aligned_mask = 0xfffffffc;
}
#if 0 /* def TV_REVERSE */
if (reverse) {
par->VPP_line_in_length_
&= 0xfffffffe;
par->VPP_hd_end_lines_
&= 0xfffffffe;
par->VPP_hd_start_lines_ =
par->VPP_hd_end_lines_ + 1
- par->VPP_line_in_length_;
} else
#endif
{
par->VPP_line_in_length_
&= aligned_mask;
par->VPP_hd_start_lines_
&= aligned_mask;
par->VPP_hd_end_lines_ =
par->VPP_hd_start_lines_ +
par->VPP_line_in_length_ - 1;
/* if have el layer, need 2 pixel align by height */
if (cur_dispbuf2) {
old_len =
par->VPP_vd_end_lines_ -
par->VPP_vd_start_lines_ + 1;
if (old_len & 1)
par->VPP_vd_end_lines_--;
if (par->VPP_vd_start_lines_ & 1) {
par->VPP_vd_start_lines_--;
par->VPP_vd_end_lines_--;
}
old_len =
par->VPP_vd_end_lines_ -
par->VPP_vd_start_lines_ + 1;
old_len = old_len >> par->vscale_skip_count;
if (par->VPP_pic_in_height_ < old_len)
par->VPP_pic_in_height_ = old_len;
}
}
}
}
void correct_vd2_mif_size_for_DV(
struct vpp_frame_par_s *par,
struct vframe_s *bl_vf)
{
int width_bl, width_el, line_in_length;
int shift;
if ((is_dolby_vision_on() == true)
&& (par->VPP_line_in_length_ > 0)
&& !is_sc_enable_before_pps(par)) {
/* work around to skip the size check when sc enable */
width_el = (cur_dispbuf2->type
& VIDTYPE_COMPRESS) ?
cur_dispbuf2->compWidth :
cur_dispbuf2->width;
width_bl = (bl_vf->type
& VIDTYPE_COMPRESS) ?
bl_vf->compWidth :
bl_vf->width;
if (width_el >= width_bl)
shift = 0;
else
shift = 1;
zoom2_start_x_lines =
par->VPP_hd_start_lines_ >> shift;
line_in_length =
par->VPP_line_in_length_ >> shift;
zoom2_end_x_lines
&= 0xfffffffe;
line_in_length
&= 0xfffffffe;
if (line_in_length > 1)
zoom2_end_x_lines =
zoom2_start_x_lines +
line_in_length - 1;
else
zoom2_end_x_lines = zoom2_start_x_lines;
zoom2_start_y_lines =
par->VPP_vd_start_lines_ >> shift;
if (zoom2_start_y_lines >= zoom2_end_y_lines)
zoom2_end_y_lines = zoom2_start_y_lines;
/* TODO: if el len is 0, need disable bl */
}
}
#if ENABLE_UPDATE_HDR_FROM_USER
void set_hdr_to_frame(struct vframe_s *vf)
{
unsigned long flags;
spin_lock_irqsave(&omx_hdr_lock, flags);
if (has_hdr_info) {
vf->prop.master_display_colour = vf_hdr;
//config static signal_type for vp9
vf->signal_type = (1 << 29)
| (5 << 26) /* unspecified */
| (0 << 25) /* limit */
| (1 << 24) /* color available */
| (9 << 16) /* 2020 */
| (16 << 8) /* 2084 */
| (9 << 0); /* 2020 */
//pr_info("set_hdr_to_frame %d, signal_type 0x%x",
//vf->prop.master_display_colour.present_flag,vf->signal_type);
}
spin_unlock_irqrestore(&omx_hdr_lock, flags);
}
#endif
static int vpp_zorder_check(void)
{
int force_flush = 0;
u32 layer0_sel = 0; /* vd1 */
u32 layer1_sel = 1; /* vd2 */
if (legacy_vpp)
return 0;
if (glayer_info[1].zorder < glayer_info[0].zorder) {
layer0_sel = 1;
layer1_sel = 0;
if ((glayer_info[0].zorder >= reference_zorder)
&& (glayer_info[1].zorder < reference_zorder))
layer0_sel++;
} else {
layer0_sel = 0;
layer1_sel = 1;
if ((glayer_info[1].zorder >= reference_zorder)
&& (glayer_info[0].zorder < reference_zorder))
layer1_sel++;
}
glayer_info[0].cur_sel_port = layer0_sel;
glayer_info[1].cur_sel_port = layer1_sel;
if ((glayer_info[0].cur_sel_port !=
glayer_info[0].last_sel_port) ||
(glayer_info[1].cur_sel_port !=
glayer_info[1].last_sel_port)) {
force_flush = 1;
glayer_info[0].last_sel_port =
glayer_info[0].cur_sel_port;
glayer_info[1].last_sel_port =
glayer_info[1].cur_sel_port;
}
return force_flush;
}
static bool black_threshold_check(u8 id)
{
struct disp_info_s *layer = NULL;
bool ret = false;
if (id >= MAX_VD_LAYERS)
return ret;
if ((black_threshold_width <= 0)
|| (black_threshold_height <= 0))
return ret;
layer = &glayer_info[id];
if ((layer->layer_top == 0)
&& (layer->layer_left == 0)
&& (layer->layer_width <= 1)
&& (layer->layer_height <= 1))
/* special case to do full screen display */
return ret;
if ((layer->layer_width <= black_threshold_width)
|| (layer->layer_height <= black_threshold_height))
ret = true;
return ret;
}
#ifdef TV_3D_FUNCTION_OPEN
inline void switch_3dView_per_vsync(void)
{
u32 start_aligned, end_aligned, block_len;
u32 FA_enable = process_3d_type & MODE_3D_OUT_FA_MASK;
if (FA_enable && (toggle_3d_fa_frame == OUT_FA_A_FRAME)) {
VSYNC_WR_MPEG_REG_BITS(VPP_MISC +
cur_dev->vpp_off, 1, 14, 1);
/* VPP_VD1_PREBLEND disable */
VSYNC_WR_MPEG_REG_BITS(VPP_MISC +
cur_dev->vpp_off, 1, 10, 1);
/* VPP_VD1_POSTBLEND disable */
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, 0x4000000);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0x4000000);
VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0x4000000);
VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0x4000000);
if (cur_dispbuf->type & VIDTYPE_COMPRESS) {
if ((process_3d_type & MODE_FORCE_3D_FA_LR)
&& (cur_frame_par->vpp_3d_mode == 1)) {
start_aligned = ori_start_x_lines;
end_aligned = ori_end_x_lines + 1;
block_len =
(end_aligned - start_aligned) / 2;
block_len = block_len /
(cur_frame_par->hscale_skip_count + 1);
VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE,
(start_aligned << 16) |
(start_aligned + block_len - 1));
}
if ((process_3d_type & MODE_FORCE_3D_FA_TB)
&& (cur_frame_par->vpp_3d_mode == 2)) {
start_aligned =
round_down(ori_start_y_lines, 4);
end_aligned =
round_up(ori_end_y_lines + 1, 4);
block_len = end_aligned - start_aligned;
block_len = block_len / 8;
VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE,
((start_aligned / 4) << 16) |
((start_aligned / 4) + block_len - 1));
}
}
} else if (FA_enable &&
(toggle_3d_fa_frame == OUT_FA_B_FRAME)) {
VSYNC_WR_MPEG_REG_BITS(VPP_MISC +
cur_dev->vpp_off, 1, 14, 1);
/* VPP_VD1_PREBLEND disable */
VSYNC_WR_MPEG_REG_BITS(VPP_MISC +
cur_dev->vpp_off, 1, 10, 1);
/* VPP_VD1_POSTBLEND disable */
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
if (cur_dispbuf->type & VIDTYPE_COMPRESS) {
if ((process_3d_type & MODE_FORCE_3D_FA_LR)
&& (cur_frame_par->vpp_3d_mode == 1)) {
start_aligned = ori_start_x_lines;
end_aligned = ori_end_x_lines + 1;
block_len =
(end_aligned - start_aligned) / 2;
block_len = block_len /
(cur_frame_par->hscale_skip_count + 1);
VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE,
((start_aligned + block_len) << 16) |
(end_aligned - 1));
}
if ((process_3d_type & MODE_FORCE_3D_FA_TB)
&& (cur_frame_par->vpp_3d_mode == 2)) {
start_aligned =
round_down(ori_start_y_lines, 4);
end_aligned =
round_up(ori_end_y_lines + 1, 4);
block_len = end_aligned - start_aligned;
block_len = block_len / 8;
VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE,
(((start_aligned / 4) + block_len) << 16) |
((end_aligned / 4) - 1));
}
}
} else if (FA_enable &&
(toggle_3d_fa_frame == OUT_FA_BANK_FRAME)) {
/* output a banking frame */
VSYNC_WR_MPEG_REG_BITS(VPP_MISC +
cur_dev->vpp_off, 0, 14, 1);
/* VPP_VD1_PREBLEND disable */
VSYNC_WR_MPEG_REG_BITS(VPP_MISC +
cur_dev->vpp_off, 0, 10, 1);
/* VPP_VD1_POSTBLEND disable */
}
if ((process_3d_type & MODE_3D_OUT_TB)
|| (process_3d_type & MODE_3D_OUT_LR)) {
if (cur_frame_par->vpp_2pic_mode &
VPP_PIC1_FIRST) {
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, 0x4000000);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0x4000000);
VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
} else {
VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL +
cur_dev->viu_off, 0x4000000);
VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL +
cur_dev->viu_off, 0x4000000);
}
}
}
#endif
#ifdef FIQ_VSYNC
void vsync_fisr_in(void)
#else
static irqreturn_t vsync_isr_in(int irq, void *dev_id)
#endif
{
int hold_line;
int enc_line;
unsigned char frame_par_di_set = 0;
s32 i, vout_type;
struct vframe_s *vf;
unsigned long flags;
#ifdef CONFIG_TVIN_VDIN
struct vdin_v4l2_ops_s *vdin_ops = NULL;
struct vdin_arg_s arg;
#endif
bool show_nosync = false;
u32 vpp_misc_save, vpp_misc_set;
int first_set = 0;
int toggle_cnt;
struct vframe_s *toggle_vf = NULL;
struct vframe_s *toggle_frame = NULL;
int video1_off_req = 0;
int video2_off_req = 0;
struct vframe_s *cur_dispbuf_back = cur_dispbuf;
static struct vframe_s *pause_vf;
int force_flush = 0;
static u32 interrupt_count;
if (debug_flag & DEBUG_FLAG_VSYNC_DONONE)
return IRQ_HANDLED;
if (frame_detect_flag == 1 &&
receive_frame_count &&
frame_detect_time &&
!atomic_read(&video_unreg_flag)) {
struct vinfo_s *video_info;
video_info = get_current_vinfo();
if (video_frame_detect.interrupt_count == 0) {
interrupt_count = 0;
video_frame_detect.interrupt_count =
frame_detect_time *
video_info->sync_duration_num /
video_info->sync_duration_den;
if (debug_flag & DEBUG_FLAG_FRAME_DETECT) {
pr_info("sync_duration_num = %d\n",
video_info->sync_duration_num);
pr_info("sync_duration_den = %d\n",
video_info->sync_duration_den);
}
video_frame_detect.start_receive_count =
receive_frame_count;
}
interrupt_count++;
if (interrupt_count == video_frame_detect.interrupt_count + 1) {
u32 receive_count;
u32 expect_frame_count;
receive_count = receive_frame_count -
video_frame_detect.start_receive_count;
expect_frame_count =
video_frame_detect.interrupt_count *
frame_detect_fps *
video_info->sync_duration_den /
video_info->sync_duration_num /
1000;
if (receive_count < expect_frame_count) {
frame_detect_drop_count +=
expect_frame_count -
receive_count;
if (debug_flag & DEBUG_FLAG_FRAME_DETECT) {
pr_info("drop_count = %d\n",
expect_frame_count -
receive_count);
}
frame_detect_receive_count +=
expect_frame_count;
} else
frame_detect_receive_count += receive_count;
if (debug_flag & DEBUG_FLAG_FRAME_DETECT) {
pr_info("expect count = %d\n",
expect_frame_count);
pr_info("receive_count = %d, time = %ds\n",
receive_count,
frame_detect_time);
pr_info("interrupt_count = %d\n",
video_frame_detect.interrupt_count);
pr_info("frame_detect_drop_count = %d\n",
frame_detect_drop_count);
pr_info("frame_detect_receive_count = %d\n",
frame_detect_receive_count);
}
interrupt_count = 0;
memset(&video_frame_detect, 0,
sizeof(struct video_frame_detect_s));
}
}
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
const char *dev_id_s = (const char *)dev_id;
int dev_id_len = strlen(dev_id_s);
if (cur_dev == &video_dev[1]) {
if (cur_dev_idx == 0) {
cur_dev = &video_dev[0];
vinfo = get_current_vinfo();
vsync_pts_inc =
90000 * vinfo->sync_duration_den /
vinfo->sync_duration_num;
vsync_pts_inc_scale = vinfo->sync_duration_den;
vsync_pts_inc_scale_base = vinfo->sync_duration_num;
video_property_changed = 1;
pr_info("Change to video 0\n");
}
} else {
if (cur_dev_idx != 0) {
cur_dev = &video_dev[1];
vinfo = get_current_vinfo2();
vsync_pts_inc =
90000 * vinfo->sync_duration_den /
vinfo->sync_duration_num;
vsync_pts_inc_scale = vinfo->sync_duration_den;
vsync_pts_inc_scale_base = vinfo->sync_duration_num;
video_property_changed = 1;
pr_info("Change to video 1\n");
}
}
if ((dev_id_s[dev_id_len - 1] == '2' && cur_dev_idx == 0) ||
(dev_id_s[dev_id_len - 1] != '2' && cur_dev_idx != 0))
return IRQ_HANDLED;
/* pr_info("%s: %s\n", __func__, dev_id_s); */
#endif
if (omx_need_drop_frame_num > 0 && !omx_drop_done && omx_secret_mode) {
struct vframe_s *vf = NULL;
while (1) {
vf = video_vf_peek();
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()
&& vf && is_dovi_frame(vf)) {
pr_info("vsync_isr_in, ignore the omx %d frames drop for dv frame\n",
omx_need_drop_frame_num);
omx_need_drop_frame_num = 0;
omx_drop_done = true;
break;
}
#endif
if (vf) {
if (omx_need_drop_frame_num >= vf->omx_index) {
//pr_info("vsync drop omx_index %d\n",
//vf->omx_index);
vf = video_vf_get();
video_vf_put(vf);
} else {
omx_drop_done = true;
break;
}
} else
break;
}
}
vf = video_vf_peek();
if (vf && !frame_render_ready) {
frame_render_ready = 1;
pr_info("amvideo_event_wait wake up!!!\n");
wake_up_interruptible(&amvideo_event_wait);
}
if ((vf) && ((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0)) {
if ((old_vmode != new_vmode) || (debug_flag == 8)) {
debug_flag = 1;
video_property_changed = 1;
pr_info("detect vout mode change!!!!!!!!!!!!\n");
old_vmode = new_vmode;
}
}
toggle_cnt = 0;
vsync_count++;
timer_count++;
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
vlock_process(vf);/*need call every vsync*/
#endif
switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
case 0:
enc_line = (READ_VCBUS_REG(ENCL_INFO_READ) >> 16) & 0x1fff;
break;
case 1:
enc_line = (READ_VCBUS_REG(ENCI_INFO_READ) >> 16) & 0x1fff;
break;
case 2:
enc_line = (READ_VCBUS_REG(ENCP_INFO_READ) >> 16) & 0x1fff;
break;
case 3:
enc_line = (READ_VCBUS_REG(ENCT_INFO_READ) >> 16) & 0x1fff;
break;
}
if (enc_line > vsync_enter_line_max)
vsync_enter_line_max = enc_line;
if (is_meson_txlx_cpu() && dmc_adjust) {
bool force_adjust = false;
struct vframe_s *chk_vf;
chk_vf = (vf != NULL) ? vf : cur_dispbuf;
if (chk_vf)
force_adjust =
(chk_vf->type & VIDTYPE_VIU_444) ? true : false;
if (chk_vf)
dmc_adjust_for_mali_vpu(
chk_vf->width,
chk_vf->height,
force_adjust);
else
dmc_adjust_for_mali_vpu(
0, 0, force_adjust);
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
vsync_rdma_config_pre();
if (to_notify_trick_wait) {
atomic_set(&trickmode_framedone, 1);
video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT;
to_notify_trick_wait = false;
goto exit;
}
if (debug_flag & DEBUG_FLAG_PRINT_RDMA) {
if (video_property_changed) {
enable_rdma_log_count = 5;
enable_rdma_log(1);
}
if (enable_rdma_log_count > 0)
enable_rdma_log_count--;
}
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
/* check video frame before VECM process */
if (is_dolby_vision_enable() && vf)
dolby_vision_check_hdr10(vf);
#endif
#ifdef CONFIG_TVIN_VDIN
/* patch for m8 4k2k wifidisplay bandwidth bottleneck */
if (get_cpu_type() == MESON_CPU_MAJOR_ID_M8) {
vdin_ops = get_vdin_v4l2_ops();
if (vdin_ops && vdin_ops->tvin_vdin_func) {
arg.cmd = VDIN_CMD_ISR;
vdin_ops->tvin_vdin_func(1, &arg);
#ifdef CONFIG_AM_VIDEO2
vdin_ops->tvin_vdin_func(0, &arg);
#endif
}
}
#endif
vout_type = detect_vout_type();
hold_line = calc_hold_line();
if (vsync_pts_inc_upint) {
if (vsync_pts_inc_adj) {
/* pr_info("adj %d, org %d\n",*/
/*vsync_pts_inc_adj, vsync_pts_inc); */
timestamp_pcrscr_inc(vsync_pts_inc_adj);
timestamp_apts_inc(vsync_pts_inc_adj);
} else {
timestamp_pcrscr_inc(vsync_pts_inc + 1);
timestamp_apts_inc(vsync_pts_inc + 1);
}
} else {
if (vsync_slow_factor == 0) {
pr_info("invalid vsync_slow_factor, set to 1\n");
vsync_slow_factor = 1;
}
if (vsync_slow_factor == 1) {
timestamp_pcrscr_inc_scale(vsync_pts_inc_scale,
vsync_pts_inc_scale_base);
timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor);
#ifdef CONFIG_AMLOGIC_VIDEOSYNC
videosync_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);
} else {
timestamp_pcrscr_inc(vsync_pts_inc / vsync_slow_factor);
timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor);
}
}
if (omx_secret_mode == true) {
u32 system_time = timestamp_pcrscr_get();
int diff = system_time - omx_pts;
if ((diff - omx_pts_interval_upper) > 0
|| (diff - omx_pts_interval_lower) < 0
|| (omx_pts_set_from_hwc_count <
OMX_MAX_COUNT_RESET_SYSTEMTIME)) {
timestamp_pcrscr_enable(1);
/*pr_info("system_time=%d, omx_pts=%d, diff=%d\n",*/
/*system_time, omx_pts, diff);*/
/*add greatest common divisor of duration*/
/*1500(60fps) 3000(30fps) 3750(24fps) for some video*/
/*that pts is not evenly*/
timestamp_pcrscr_set(omx_pts + DURATION_GCD);
} else if (is_dolby_vision_enable()
&& ((diff - omx_pts_dv_upper) > 0
|| (diff - omx_pts_dv_lower) < 0)) {
timestamp_pcrscr_set(omx_pts + DURATION_GCD);
}
} else
omx_pts = 0;
if (trickmode_duration_count > 0)
trickmode_duration_count -= vsync_pts_inc;
#ifdef VIDEO_PTS_CHASE
if (vpts_chase)
vpts_chase_counter--;
#endif
if (slowsync_repeat_enable)
frame_repeat_count++;
if (smooth_sync_enable) {
if (video_frame_repeat_count)
video_frame_repeat_count++;
}
if (atomic_read(&video_unreg_flag))
goto exit;
if (atomic_read(&video_pause_flag)
&& (!((video_global_output == 1)
&& (video_enabled != video_status_saved))))
goto exit;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_vsync_rdma_enable()) {
rdma_canvas_id = next_rdma_canvas_id;
#ifdef VIDEO_PIP
pip_rdma_canvas_id = pip_next_rdma_canvas_id;
#endif
} else {
if (rdma_enable_pre)
goto exit;
rdma_canvas_id = 0;
next_rdma_canvas_id = 1;
#ifdef VIDEO_PIP
pip_rdma_canvas_id = 0;
pip_next_rdma_canvas_id = 1;
#endif
}
for (i = 0; i < dispbuf_to_put_num; i++) {
if (dispbuf_to_put[i]) {
video_vf_put(dispbuf_to_put[i]);
dispbuf_to_put[i] = NULL;
}
dispbuf_to_put_num = 0;
}
#ifdef VIDEO_PIP
if (pipbuf_to_put) {
pip_vf_put(pipbuf_to_put);
pipbuf_to_put = NULL;
}
#endif
#endif
if ((!cur_dispbuf) || (cur_dispbuf == &vf_local)) {
vf = video_vf_peek();
if (vf) {
if (hdmi_in_onvideo == 0) {
if (nopostvideostart == false)
tsync_avevent_locked(VIDEO_START,
(vf->pts) ? vf->pts :
timestamp_vpts_get());
video_start_post = true;
}
if (show_first_frame_nosync || show_first_picture)
show_nosync = true;
if (slowsync_repeat_enable)
frame_repeat_count = 0;
} else if ((cur_dispbuf == &vf_local)
&& (video_property_changed)) {
if (!(blackout | force_blackout)) {
if (cur_dispbuf
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
&& ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1)
== 0)
#endif
) {
/* setting video display*/
/*property in unregister mode */
u32 cur_index =
READ_VCBUS_REG(VD1_IF0_CANVAS0 +
cur_dev->viu_off);
if ((get_cpu_type() >=
MESON_CPU_MAJOR_ID_GXBB) &&
(cur_dispbuf->type &
VIDTYPE_COMPRESS)) {
cur_dispbuf->compHeadAddr =
READ_VCBUS_REG(AFBC_HEAD_BADDR)
<< 4;
} else {
cur_dispbuf->canvas0Addr =
cur_index;
}
}
vsync_toggle_frame(cur_dispbuf, __LINE__);
} else
video_property_changed = 0;
} else {
goto SET_FILTER;
}
}
/* buffer switch management */
vf = video_vf_peek();
/* setting video display property in underflow mode */
if ((!vf) && cur_dispbuf && (video_property_changed))
vsync_toggle_frame(cur_dispbuf, __LINE__);
/*debug info for skip & repeate vframe case*/
if (!vf) {
underflow++;
ATRACE_COUNTER("underflow", 1);
if (video_dbg_vf&(1<<0))
dump_vframe_status("vdin0");
if (video_dbg_vf&(1<<1))
dump_vframe_status("deinterlace");
if (video_dbg_vf&(1<<2))
dump_vframe_status("amlvideo2");
if (video_dbg_vf&(1<<3))
dump_vframe_status("ppmgr");
if (video_dbg_vf&(1<<4))
dump_vdin_reg();
} else {
ATRACE_COUNTER("underflow", 0);
}
video_get_vf_cnt = 0;
if (platform_type == 1) {
/* toggle_3d_fa_frame*/
/* determine the out frame is L or R or blank */
judge_3d_fa_out_mode();
}
while (vf) {
if (vpts_expire(cur_dispbuf, vf, toggle_cnt) || show_nosync) {
ATRACE_COUNTER(MODULE_NAME, __LINE__);
if (debug_flag & DEBUG_FLAG_PTS_TRACE)
pr_info("vpts = 0x%x, c.dur=0x%x, n.pts=0x%x, scr = 0x%x, pcr-pts-diff=%d, ptstrace=%d\n",
timestamp_vpts_get(),
(cur_dispbuf) ?
cur_dispbuf->duration : 0,
vf->pts, timestamp_pcrscr_get(),
timestamp_pcrscr_get() - vf->pts +
vsync_pts_align,
pts_trace);
amlog_mask_if(toggle_cnt > 0, LOG_MASK_FRAMESKIP,
"skipped\n");
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()
&& dolby_vision_need_wait())
break;
#endif
#if ENABLE_UPDATE_HDR_FROM_USER
set_hdr_to_frame(vf);
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
refresh_on_vs(vf);
if (amvecm_on_vs(
(cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
cur_frame_par ?
cur_frame_par->supsc1_hori_ratio :
0,
cur_frame_par ?
cur_frame_par->supsc1_vert_ratio :
0) == 1)
break;
#endif
/*
*two special case:
*case1:4k display case,input buffer not enough &
* quickly for display
*case2:input buffer all not OK
*/
if (vf && hdmiin_frame_check &&
(vf->source_type == VFRAME_SOURCE_TYPE_HDMI) &&
(video_vf_disp_mode_get(vf) ==
VFRAME_DISP_MODE_UNKNOWN) &&
(hdmiin_frame_check_cnt++ < 10))
break;
else
hdmiin_frame_check_cnt = 0;
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 && hdmiin_frame_check && (vf->source_type ==
VFRAME_SOURCE_TYPE_HDMI) &&
video_vf_disp_mode_check(vf))
break;
force_blackout = 0;
if ((platform_type == 1) ||
(platform_type == 0)) {
if (vf) {
if (last_mode_3d !=
vf->mode_3d_enable) {
last_mode_3d =
vf->mode_3d_enable;
mode_3d_changed = 1;
}
video_3d_format = vf->trans_fmt;
}
}
vsync_toggle_frame(vf, __LINE__);
toggle_frame = vf;
/* The v4l2 capture needs a empty vframe to flush */
if (has_receive_dummy_vframe())
break;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()) {
toggle_vf = dolby_vision_toggle_frame(vf);
video_pause_global = 0;
} else
#endif
{
cur_dispbuf2 = NULL;
video_pause_global = 2;
pause_vf = NULL;
}
if (trickmode_fffb == 1) {
trickmode_vpts = vf->pts;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1)
!= 0) {
atomic_set(&trickmode_framedone, 1);
video_notify_flag |=
VIDEO_NOTIFY_TRICK_WAIT;
} else
#endif
to_notify_trick_wait = true;
#else
atomic_set(&trickmode_framedone, 1);
video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT;
#endif
break;
}
if (slowsync_repeat_enable)
frame_repeat_count = 0;
vf = video_vf_peek();
if (!vf)
next_peek_underflow++;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (for_dolby_vision_certification()
&& toggle_vf)
break;
#endif
if (debug_flag & DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC)
break;
video_get_vf_cnt++;
if (video_get_vf_cnt >= 2)
video_drop_vf_cnt++;
} else {
ATRACE_COUNTER(MODULE_NAME, __LINE__);
/* check if current frame's duration has expired,
*in this example
* it compares current frame display duration
* with 1/1/1/1.5 frame duration
* every 4 frames there will be one frame play
* longer than usual.
* you can adjust this array for any slow sync
* control as you want.
* The playback can be smoother than previous method.
*/
if (slowsync_repeat_enable) {
ATRACE_COUNTER(MODULE_NAME, __LINE__);
if (duration_expire
(cur_dispbuf, vf,
frame_repeat_count * vsync_pts_inc)
&& timestamp_pcrscr_enable_state()) {
amlog_mask(LOG_MASK_SLOWSYNC,
"slow sync toggle,repeat_count = %d\n",
frame_repeat_count);
amlog_mask(LOG_MASK_SLOWSYNC,
"sys.time = 0x%x, video time = 0x%x\n",
timestamp_pcrscr_get(),
timestamp_vpts_get());
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()
&& dolby_vision_need_wait())
break;
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
refresh_on_vs(vf);
if (amvecm_on_vs(
(cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
vf, CSC_FLAG_CHECK_OUTPUT,
cur_frame_par ?
cur_frame_par->supsc1_hori_ratio
: 0,
cur_frame_par ?
cur_frame_par->supsc1_vert_ratio
: 0) == 1)
break;
#endif
vf = video_vf_get();
if (!vf) {
ATRACE_COUNTER(MODULE_NAME,
__LINE__);
break;
}
vsync_toggle_frame(vf, __LINE__);
toggle_frame = vf;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable())
toggle_vf =
dolby_vision_toggle_frame(vf);
else
#endif
cur_dispbuf2 = NULL;
frame_repeat_count = 0;
vf = video_vf_peek();
} else if ((cur_dispbuf) &&
(cur_dispbuf->duration_pulldown >
vsync_pts_inc)) {
frame_count++;
cur_dispbuf->duration_pulldown -=
PTS2DUR(vsync_pts_inc);
}
} else {
if ((cur_dispbuf)
&& (cur_dispbuf->duration_pulldown >
vsync_pts_inc)) {
frame_count++;
cur_dispbuf->duration_pulldown -=
PTS2DUR(vsync_pts_inc);
}
}
/* setting video display property in pause mode */
if (video_property_changed && cur_dispbuf) {
if (blackout | force_blackout) {
if (cur_dispbuf != &vf_local)
vsync_toggle_frame(
cur_dispbuf,
__LINE__);
} else
vsync_toggle_frame(cur_dispbuf,
__LINE__);
if (is_dolby_vision_enable()) {
pause_vf = cur_dispbuf;
video_pause_global = 1;
} else {
pause_vf = NULL;
video_pause_global = 2;
}
}
if (pause_vf && (video_pause_global == 1)
&& is_dolby_vision_enable()) {
toggle_vf = pause_vf;
dolby_vision_parse_metadata(
pause_vf, 0, false);
dolby_vision_set_toggle_flag(1);
}
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
if (video_get_vf_cnt == 0)
video_repeat_vf_cnt++;
SET_FILTER:
#ifdef VIDEO_PIP
vf = pip_vf_peek();
/* setting video display property in underflow mode */
if ((!vf) && cur_pipbuf && (pip_property_changed))
pip_toggle_frame(cur_pipbuf);
if (vf) {
vf = pip_vf_get();
if (vf) {
if (!vf->frame_dirty)
pip_toggle_frame(vf);
else
pip_vf_put(vf);
}
}
#endif
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
amvecm_on_vs(
(cur_dispbuf != &vf_local)
? cur_dispbuf : NULL,
toggle_frame,
toggle_frame ? CSC_FLAG_TOGGLE_FRAME : 0,
cur_frame_par ?
cur_frame_par->supsc1_hori_ratio :
0,
cur_frame_par ?
cur_frame_par->supsc1_vert_ratio :
0);
#endif
/* filter setting management */
if ((frame_par_ready_to_set) || (frame_par_force_to_set)) {
cur_frame_par = next_frame_par;
frame_par_di_set = 1;
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()) {
u32 frame_size = 0, h_size, v_size;
u8 pps_state = 0; /* pps no change */
/* force toggle when keeping frame after playing */
if ((cur_dispbuf == &vf_local)
&& !toggle_vf
&& is_dolby_vision_on()) {
toggle_vf = cur_dispbuf;
dolby_vision_parse_metadata(
cur_dispbuf, 2, false);
dolby_vision_set_toggle_flag(1);
}
/* pause mode was moved to video display property */
#if 0
/* force toggle in pause mode */
if (cur_dispbuf
&& (cur_dispbuf != &vf_local)
&& !toggle_vf
&& is_dolby_vision_on()
&& !for_dolby_vision_certification()) {
toggle_vf = cur_dispbuf;
dolby_vision_parse_metadata(
cur_dispbuf, 0, false);
dolby_vision_set_toggle_flag(1);
}
#endif
if (cur_frame_par) {
if (frame_par_ready_to_set || frame_par_force_to_set) {
struct vppfilter_mode_s *vpp_filter =
&cur_frame_par->vpp_filter;
if ((vpp_filter->vpp_hsc_start_phase_step
== 0x1000000) &&
(vpp_filter->vpp_vsc_start_phase_step
== 0x1000000) &&
(vpp_filter->vpp_hsc_start_phase_step ==
vpp_filter->vpp_hf_start_phase_step) &&
!vpp_filter->vpp_pre_vsc_en &&
!vpp_filter->vpp_pre_hsc_en &&
!cur_frame_par->supsc0_enable &&
!cur_frame_par->supsc1_enable &&
bypass_pps)
pps_state = 2; /* pps disable */
else
pps_state = 1; /* pps enable */
}
if (cur_frame_par->VPP_hd_start_lines_
>= cur_frame_par->VPP_hd_end_lines_)
h_size = 0;
else
h_size = cur_frame_par->VPP_hd_end_lines_
- cur_frame_par->VPP_hd_start_lines_ + 1;
h_size /= (cur_frame_par->hscale_skip_count + 1);
if (cur_frame_par->VPP_vd_start_lines_
>= cur_frame_par->VPP_vd_end_lines_)
v_size = 0;
else
v_size = cur_frame_par->VPP_vd_end_lines_
- cur_frame_par->VPP_vd_start_lines_ + 1;
v_size /= (cur_frame_par->vscale_skip_count + 1);
frame_size = (h_size << 16) | v_size;
} else if (toggle_vf) {
h_size = (toggle_vf->type & VIDTYPE_COMPRESS) ?
toggle_vf->compWidth : toggle_vf->width;
v_size = (toggle_vf->type & VIDTYPE_COMPRESS) ?
toggle_vf->compHeight : toggle_vf->height;
frame_size = (h_size << 16) | v_size;
}
dolby_vision_process(toggle_vf, frame_size, pps_state);
dolby_vision_update_setting();
}
#endif
if ((platform_type == 1) || (platform_type == 0)) {
if (mode_3d_changed) {
mode_3d_changed = 0;
frame_par_force_to_set = 1;
}
}
if (cur_dispbuf_back != cur_dispbuf) {
display_frame_count++;
drop_frame_count = receive_frame_count - display_frame_count;
}
if (cur_dispbuf) {
struct f2v_vphase_s *vphase;
u32 vin_type = cur_dispbuf->type & VIDTYPE_TYPEMASK;
{
int need_afbc = (cur_dispbuf->type & VIDTYPE_COMPRESS);
int afbc_need_reset =
video_enabled &&
need_afbc &&
(!(READ_VCBUS_REG(AFBC_ENABLE) & 0x100));
/*video on && afbc is off && is compress frame.*/
if (frame_par_ready_to_set || afbc_need_reset) {
if (cur_frame_par) {
viu_set_dcu(cur_frame_par, cur_dispbuf);
if (cur_dispbuf2)
vd2_set_dcu(cur_frame_par,
cur_dispbuf2);
}
} else if (cur_dispbuf2) {
u32 new_el_w =
(cur_dispbuf2->type
& VIDTYPE_COMPRESS) ?
cur_dispbuf2->compWidth :
cur_dispbuf2->width;
if (new_el_w != last_el_w) {
pr_info("reset vd2 dcu for el change, %d->%d, %p--%p\n",
last_el_w, new_el_w,
cur_dispbuf, cur_dispbuf2);
vd2_set_dcu(cur_frame_par,
cur_dispbuf2);
}
} else {
last_el_w = 0;
last_el_status = 0;
}
}
if (cur_frame_par &&
cur_frame_par->hscale_skip_count) {
VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL +
cur_dev->viu_off, 1, 20, 1);
/* HFORMATTER_EN */
#ifdef VIDEO_PIP
if (!cur_pipbuf)
#endif
VSYNC_WR_MPEG_REG_BITS(VIU_VD2_FMT_CTRL +
cur_dev->viu_off, 1, 20, 1);
/* HFORMATTER_EN */
}
#ifdef TV_3D_FUNCTION_OPEN
switch_3dView_per_vsync();
#endif
/* vertical phase */
vphase = &cur_frame_par->VPP_vf_ini_phase_
[vpp_phase_table[vin_type]
[vout_type]];
VSYNC_WR_MPEG_REG(
VPP_VSC_INI_PHASE + cur_dev->vpp_off,
((u32) (vphase->phase) << 8));
if (vphase->repeat_skip >= 0) {
/* skip lines */
VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL +
cur_dev->vpp_off,
skip_tab[vphase->repeat_skip],
VPP_PHASECTL_INIRCVNUMT_BIT,
VPP_PHASECTL_INIRCVNUM_WID +
VPP_PHASECTL_INIRPTNUM_WID);
} else {
/* repeat first line */
VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL +
cur_dev->vpp_off, 4,
VPP_PHASECTL_INIRCVNUMT_BIT,
VPP_PHASECTL_INIRCVNUM_WID);
VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL +
cur_dev->vpp_off,
1 - vphase->repeat_skip,
VPP_PHASECTL_INIRPTNUMT_BIT,
VPP_PHASECTL_INIRPTNUM_WID);
}
if (force_3d_scaler == 3 &&
cur_frame_par &&
cur_frame_par->vpp_3d_scale) {
VSYNC_WR_MPEG_REG_BITS(
VPP_VSC_PHASE_CTRL, 3,
VPP_PHASECTL_DOUBLELINE_BIT, 2);
} else if (force_3d_scaler == 1 &&
cur_frame_par &&
cur_frame_par->vpp_3d_scale) {
VSYNC_WR_MPEG_REG_BITS(
VPP_VSC_PHASE_CTRL, 1,
VPP_PHASECTL_DOUBLELINE_BIT,
VPP_PHASECTL_DOUBLELINE_WID);
} else if (force_3d_scaler == 2 &&
cur_frame_par &&
cur_frame_par->vpp_3d_scale) {
VSYNC_WR_MPEG_REG_BITS(
VPP_VSC_PHASE_CTRL, 2,
VPP_PHASECTL_DOUBLELINE_BIT, 2);
} else {
VSYNC_WR_MPEG_REG_BITS(
VPP_VSC_PHASE_CTRL, 0,
VPP_PHASECTL_DOUBLELINE_BIT, 2);
}
}
#ifdef VIDEO_PIP
if (pip_frame_ready_to_set)
curpip_frame_par = nextpip_frame_par;
if (cur_pipbuf) {
int need_afbc = (cur_pipbuf->type & VIDTYPE_COMPRESS);
int afbc_need_reset =
video2_enabled &&
need_afbc &&
(!(READ_VCBUS_REG(VD2_AFBC_ENABLE) & 0x100));
/*video on && afbc is off && is compress frame.*/
if (pip_frame_ready_to_set || afbc_need_reset)
pip_set_dcu(curpip_frame_par, cur_pipbuf);
if (cur_pipbuf && curpip_frame_par) {
if (curpip_frame_par->hscale_skip_count) {
VSYNC_WR_MPEG_REG_BITS(
VIU_VD2_FMT_CTRL +
cur_dev->viu_off, 1, 20, 1);
/* HFORMATTER_EN */
}
proc_vd2_vsc_phase_per_vsync(
curpip_frame_par, cur_pipbuf, vout_type);
}
}
if (pip_frame_ready_to_set) {
#if 0
u32 h_size, v_size;
if (pip_start_x_lines < pip_end_x_lines)
h_size = pip_end_x_lines - pip_start_x_lines + 1;
else
h_size = ori2_end_x_lines - ori2_start_x_lines + 1;
if (pip_start_y_lines < pip_end_y_lines)
v_size = pip_end_y_lines - pip_start_y_lines + 1;
else
v_size = ori2_end_y_lines - ori2_start_y_lines + 1;
zoom2_start_x_lines = ori2_start_x_lines;
zoom2_end_x_lines = ori2_end_x_lines;
zoom2_start_y_lines = ori2_start_y_lines;
zoom2_end_y_lines = ori2_end_y_lines;
if (h_size < (zoom2_end_x_lines - zoom2_start_x_lines + 1))
zoom2_end_x_lines = zoom2_start_x_lines + h_size - 1;
else if (h_size > (zoom2_end_x_lines - zoom2_start_x_lines + 1))
h_size = zoom2_end_x_lines - zoom2_start_x_lines + 1;
if (v_size < (zoom2_end_y_lines - zoom2_start_y_lines + 1))
zoom2_end_y_lines = zoom2_start_y_lines + v_size - 1;
else if (v_size > (zoom2_end_y_lines - zoom2_start_y_lines + 1))
v_size = (zoom2_end_y_lines - zoom2_start_y_lines + 1);
if (vinfo) {
if (pip_start_x_lines + h_size > vinfo->width) {
h_size = vinfo->width - pip_start_x_lines;
zoom2_end_x_lines =
zoom2_start_x_lines + h_size - 1;
}
if (pip_start_y_lines + v_size > vinfo->height) {
v_size = vinfo->height - pip_start_y_lines;
zoom2_end_y_lines =
zoom2_start_y_lines + v_size - 1;
}
}
#endif
struct scaler_setting_s local_pps;
struct blend_setting_s local_blend;
struct vpp_frame_par_s *par = curpip_frame_par;
if (cur_pipbuf->type & VIDTYPE_INTERLACE) {
if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) {
zoom2_start_y_lines =
par->VPP_vd_start_lines_ >> 1;
zoom2_end_y_lines =
((par->VPP_vd_end_lines_ + 1)
>> 1) - 1;
} else {
zoom2_start_y_lines =
par->VPP_vd_start_lines_;
zoom2_end_y_lines =
par->VPP_vd_end_lines_;
}
} else {
if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) {
zoom2_start_y_lines =
par->VPP_vd_start_lines_;
zoom2_end_y_lines =
par->VPP_vd_end_lines_;
} else {
zoom2_start_y_lines =
par->VPP_vd_start_lines_ >> 1;
zoom2_end_y_lines =
((par->VPP_vd_end_lines_ + 1)
>> 1) - 1;
}
}
zoom2_start_x_lines =
par->VPP_hd_start_lines_;
zoom2_end_x_lines =
par->VPP_hd_end_lines_;
config_vd_pps(
1, par, &local_pps, vinfo);
config_vd_blend(
1, par, cur_pipbuf,
(legacy_vpp ? 0x1ff : 0x100), &local_blend);
vd2_scaler_setting(&local_pps);
vd2_zoom_display_horz(
cur_pipbuf,
par->hscale_skip_count);
vd2_zoom_display_vert(
cur_pipbuf,
par->vscale_skip_count);
vd2_vpp_blend_setting(&local_blend);
pip_frame_ready_to_set = 0;
}
#endif
if (((frame_par_ready_to_set) || (frame_par_force_to_set)) &&
(cur_frame_par)) {
struct vppfilter_mode_s *vpp_filter =
&cur_frame_par->vpp_filter;
if (cur_dispbuf) {
u32 zoom_start_y, zoom_end_y;
correct_vd1_mif_size_for_DV(cur_frame_par);
if (cur_dispbuf->type & VIDTYPE_INTERLACE) {
if (cur_dispbuf->type
& VIDTYPE_COMPRESS) {
/* for vdin afbc and interlace case */
zoom_start_y =
cur_frame_par->VPP_vd_start_lines_;
zoom_end_y =
cur_frame_par->VPP_vd_end_lines_;
} else if (cur_dispbuf->type
& VIDTYPE_VIU_FIELD) {
zoom_start_y =
cur_frame_par->VPP_vd_start_lines_
>> 1;
zoom_end_y =
((cur_frame_par->VPP_vd_end_lines_ + 1)
>> 1) - 1;
} else {
zoom_start_y =
cur_frame_par->VPP_vd_start_lines_;
zoom_end_y =
cur_frame_par->VPP_vd_end_lines_;
}
} else {
if (cur_dispbuf->type & VIDTYPE_VIU_FIELD) {
zoom_start_y =
cur_frame_par->VPP_vd_start_lines_;
zoom_end_y =
cur_frame_par->VPP_vd_end_lines_;
} else {
if (is_need_framepacking_output()) {
zoom_start_y =
cur_frame_par->VPP_vd_start_lines_ >> 1;
zoom_end_y =
((cur_frame_par->VPP_vd_end_lines_
- framepacking_blank + 1) >> 1) - 1;
} else {
zoom_start_y =
cur_frame_par->VPP_vd_start_lines_ >> 1;
zoom_end_y =
((cur_frame_par->VPP_vd_end_lines_ + 1) >> 1) - 1;
}
}
}
zoom_start_x_lines =
cur_frame_par->VPP_hd_start_lines_;
zoom_end_x_lines = cur_frame_par->VPP_hd_end_lines_;
zoom_display_horz(cur_dispbuf,
cur_frame_par->hscale_skip_count);
zoom_start_y_lines = zoom_start_y;
zoom_end_y_lines = zoom_end_y;
zoom_display_vert(cur_dispbuf);
if (is_dolby_vision_enable() && cur_dispbuf2) {
zoom2_start_x_lines = ori2_start_x_lines;
zoom2_end_x_lines = ori2_end_x_lines;
zoom2_start_y_lines = ori2_start_y_lines;
zoom2_end_y_lines = ori2_end_y_lines;
correct_vd2_mif_size_for_DV(
cur_frame_par, cur_dispbuf);
vd2_zoom_display_horz(cur_dispbuf2,
cur_frame_par->hscale_skip_count);
vd2_zoom_display_vert(cur_dispbuf2,
cur_frame_par->vscale_skip_count);
}
}
/*vpp input size setting*/
VSYNC_WR_MPEG_REG(VPP_IN_H_V_SIZE,
((cur_frame_par->video_input_w & 0x1fff) <<
16) | (cur_frame_par->video_input_h & 0x1fff));
/* vpp super scaler */
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) {
vpp_set_super_scaler_regs(cur_frame_par->supscl_path,
cur_frame_par->supsc0_enable,
cur_frame_par->spsc0_w_in,
cur_frame_par->spsc0_h_in,
cur_frame_par->supsc0_hori_ratio,
cur_frame_par->supsc0_vert_ratio,
cur_frame_par->supsc1_enable,
cur_frame_par->spsc1_w_in,
cur_frame_par->spsc1_h_in,
cur_frame_par->supsc1_hori_ratio,
cur_frame_par->supsc1_vert_ratio,
vinfo->width,
vinfo->height);
if (is_dolby_vision_on() &&
is_dolby_vision_stb_mode() &&
!cur_frame_par->supsc0_enable &&
!cur_frame_par->supsc1_enable) {
VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0);
VSYNC_WR_MPEG_REG(VPP_SRSHARP1_CTRL, 0);
}
}
/* vpp filters */
/* SET_MPEG_REG_MASK(VPP_SC_MISC + cur_dev->vpp_off, */
/* VPP_SC_TOP_EN | VPP_SC_VERT_EN | VPP_SC_HORZ_EN); */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (for_dolby_vision_certification()) {
/* turn off PPS for Dolby Vision certification */
VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off,
0, VPP_SC_TOP_EN_BIT, VPP_SC_TOP_EN_WID);
} else
#endif
{
VSYNC_WR_MPEG_REG(VPP_SC_MISC + cur_dev->vpp_off,
READ_VCBUS_REG(VPP_SC_MISC +
cur_dev->vpp_off) |
VPP_SC_TOP_EN | VPP_SC_VERT_EN |
VPP_SC_HORZ_EN);
/* pps pre hsc&vsc en */
VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off,
vpp_filter->vpp_pre_hsc_en,
VPP_SC_PREHORZ_EN_BIT, 1);
VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off,
vpp_filter->vpp_pre_vsc_en,
VPP_SC_PREVERT_EN_BIT, 1);
VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off,
vpp_filter->vpp_pre_vsc_en,
VPP_LINE_BUFFER_EN_BIT, 1);
}
/* for bypass pps debug */
if ((vpp_filter->vpp_hsc_start_phase_step == 0x1000000) &&
(vpp_filter->vpp_vsc_start_phase_step == 0x1000000) &&
(vpp_filter->vpp_hsc_start_phase_step ==
vpp_filter->vpp_hf_start_phase_step) &&
!vpp_filter->vpp_pre_vsc_en &&
!vpp_filter->vpp_pre_hsc_en &&
bypass_pps)
VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off,
0, VPP_SC_TOP_EN_BIT, VPP_SC_TOP_EN_WID);
/*turn off vertical scaler when 3d display */
/* CLEAR_MPEG_REG_MASK(VPP_SC_MISC,VPP_SC_VERT_EN); */
if (platform_type == 1) {
if (last_mode_3d) {
VSYNC_WR_MPEG_REG(
VPP_SC_MISC + cur_dev->vpp_off,
READ_MPEG_REG(VPP_SC_MISC +
cur_dev->vpp_off) &
(~VPP_SC_VERT_EN));
}
}
/* horitontal filter settings */
VSYNC_WR_MPEG_REG_BITS(
VPP_SC_MISC + cur_dev->vpp_off,
vpp_filter->vpp_horz_coeff[0],
VPP_SC_HBANK_LENGTH_BIT,
VPP_SC_BANK_LENGTH_WID);
/* fix the pps last line dummy issue */
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B))
VSYNC_WR_MPEG_REG_BITS(
VPP_SC_MISC + cur_dev->vpp_off,
1, 24, 1);
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
&& !is_meson_mtvd_cpu()) {
VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL +
cur_dev->vpp_off,
(vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0,
VPP_PHASECTL_DOUBLELINE_BIT,
VPP_PHASECTL_DOUBLELINE_WID);
}
/* #endif */
if (vpp_filter->vpp_horz_coeff[1] & 0x8000) {
VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX +
cur_dev->vpp_off,
VPP_COEF_HORZ | VPP_COEF_9BIT);
} else {
VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX +
cur_dev->vpp_off,
VPP_COEF_HORZ);
}
for (i = 0; i < (vpp_filter->vpp_horz_coeff[1] & 0xff); i++) {
VSYNC_WR_MPEG_REG(VPP_SCALE_COEF + cur_dev->vpp_off,
vpp_filter->vpp_horz_coeff[i + 2]);
}
/* vertical filter settings */
VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off,
vpp_filter->vpp_vert_coeff[0],
VPP_SC_VBANK_LENGTH_BIT,
VPP_SC_BANK_LENGTH_WID);
VSYNC_WR_MPEG_REG(VPP_SCALE_COEF_IDX + cur_dev->vpp_off,
VPP_COEF_VERT);
for (i = 0; i < vpp_filter->vpp_vert_coeff[1]; i++) {
VSYNC_WR_MPEG_REG(VPP_SCALE_COEF + cur_dev->vpp_off,
vpp_filter->vpp_vert_coeff[i + 2]);
}
/* vertical chroma filter settings */
if (vpp_filter->vpp_vert_chroma_filter_en) {
const u32 *pCoeff = vpp_filter->vpp_vert_chroma_coeff;
VSYNC_WR_MPEG_REG(
VPP_SCALE_COEF_IDX + cur_dev->vpp_off,
VPP_COEF_VERT_CHROMA|VPP_COEF_SEP_EN);
for (i = 0; i < pCoeff[1]; i++)
VSYNC_WR_MPEG_REG(
VPP_SCALE_COEF + cur_dev->vpp_off,
pCoeff[i + 2]);
}
/* work around to cut the last green line
*when two layer dv display and do vskip
*/
if (is_dolby_vision_on() &&
(cur_frame_par->vscale_skip_count > 0)
&& cur_dispbuf2
&& (cur_frame_par->VPP_pic_in_height_ > 0))
cur_frame_par->VPP_pic_in_height_--;
VSYNC_WR_MPEG_REG(VPP_PIC_IN_HEIGHT + cur_dev->vpp_off,
cur_frame_par->VPP_pic_in_height_);
VSYNC_WR_MPEG_REG_BITS(VPP_HSC_PHASE_CTRL + cur_dev->vpp_off,
cur_frame_par->VPP_hf_ini_phase_,
VPP_HSC_TOP_INI_PHASE_BIT,
VPP_HSC_TOP_INI_PHASE_WID);
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END +
cur_dev->vpp_off,
((cur_frame_par->VPP_post_blend_vd_h_start_ &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
((cur_frame_par->VPP_post_blend_vd_h_end_ &
VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_V_START_END +
cur_dev->vpp_off,
((cur_frame_par->VPP_post_blend_vd_v_start_ &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
((cur_frame_par->VPP_post_blend_vd_v_end_ &
VPP_VD_SIZE_MASK)
<< VPP_VD1_END_BIT));
if ((cur_frame_par->VPP_post_blend_vd_v_end_ -
cur_frame_par->VPP_post_blend_vd_v_start_ + 1) > 1080) {
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END +
cur_dev->vpp_off,
((cur_frame_par->VPP_post_blend_vd_v_start_ &
VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) |
((cur_frame_par->VPP_post_blend_vd_v_end_ &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
} else {
VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END +
cur_dev->vpp_off,
((0 & VPP_VD_SIZE_MASK) <<
VPP_VD1_START_BIT) | ((1079 &
VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT));
}
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG(
VPP_PREBLEND_H_SIZE + cur_dev->vpp_off,
(cur_frame_par->video_input_h << 16)
| cur_frame_par->video_input_w);
VSYNC_WR_MPEG_REG(
VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off,
((cur_frame_par->VPP_post_blend_vd_v_end_ + 1)
<< 16) |
cur_frame_par->VPP_post_blend_h_size_);
} else {
VSYNC_WR_MPEG_REG(
VPP_PREBLEND_H_SIZE + cur_dev->vpp_off,
cur_frame_par->VPP_line_in_length_);
VSYNC_WR_MPEG_REG(
VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off,
cur_frame_par->VPP_post_blend_h_size_);
}
vpp_settings_h(cur_frame_par);
vpp_settings_v(cur_frame_par);
if (is_dolby_vision_enable() && cur_dispbuf2) {
vd2_settings_h(cur_dispbuf2);
vd2_settings_v(cur_dispbuf2);
}
frame_par_ready_to_set = 0;
frame_par_force_to_set = 0;
first_set = 1;
}
/* VPP one time settings */
wait_sync = 0;
if (!legacy_vpp && vinfo) {
u32 read_value = VSYNC_RD_MPEG_REG(
VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off);
if (((vinfo->field_height << 16) | vinfo->width)
!= read_value)
VSYNC_WR_MPEG_REG(
VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off,
((vinfo->field_height << 16) | vinfo->width));
} else if (vinfo) {
if (VSYNC_RD_MPEG_REG(
VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off)
!= vinfo->width)
VSYNC_WR_MPEG_REG(
VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off,
vinfo->width);
}
if (cur_dispbuf && cur_dispbuf->process_fun) {
/* for new deinterlace driver */
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (debug_flag & DEBUG_FLAG_PRINT_RDMA) {
if (enable_rdma_log_count > 0)
pr_info("call process_fun\n");
}
#endif
cur_dispbuf->process_fun(cur_dispbuf->private_data,
zoom_start_x_lines |
(cur_frame_par->vscale_skip_count <<
24) | (frame_par_di_set << 16),
zoom_end_x_lines, zoom_start_y_lines,
zoom_end_y_lines, cur_dispbuf);
}
exit:
#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG)
pts_trace++;
#endif
vpp_misc_save = READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off);
vpp_misc_set = vpp_misc_save;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
if (!is_dolby_vision_on())
vpp_misc_set |= VPP_CM_ENABLE;
else
vpp_misc_set &= ~VPP_CM_ENABLE;
#endif
if (bypass_cm)
vpp_misc_set &= ~VPP_CM_ENABLE;
if (update_osd_vpp_misc && legacy_vpp) {
vpp_misc_set &= ~osd_vpp_misc_mask;
vpp_misc_set |=
(osd_vpp_misc & osd_vpp_misc_mask);
if (vpp_misc_set &
(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND))
vpp_misc_set |= VPP_POSTBLEND_EN;
}
#ifdef VIDEO_PIP
if (cur_pipbuf && (video2_enabled == 1)
&& ((vpp_misc_save & VPP_VD2_POSTBLEND) == 0)
&& (video2_onoff_state == VIDEO_ENABLE_STATE_IDLE)) {
vpp_misc_set |=
VPP_VD2_POSTBLEND |
VPP_POSTBLEND_EN;
}
#endif
if ((video_enabled == 1) && ((vpp_misc_save & VPP_VD1_POSTBLEND) == 0)
&& (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) {
vpp_misc_set |=
VPP_VD1_PREBLEND |
VPP_VD1_POSTBLEND |
VPP_POSTBLEND_EN;
}
if ((video_enabled == 1) && cur_frame_par
&& (cur_dispbuf != &vf_local) && (first_set == 0)
&& (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) {
struct vppfilter_mode_s *vpp_filter =
&cur_frame_par->vpp_filter;
u32 h_phase_step, v_phase_step;
h_phase_step = READ_VCBUS_REG(
VPP_HSC_START_PHASE_STEP + cur_dev->vpp_off);
v_phase_step = READ_VCBUS_REG(
VPP_VSC_START_PHASE_STEP + cur_dev->vpp_off);
if ((vpp_filter->vpp_hf_start_phase_step != h_phase_step) ||
(vpp_filter->vpp_vsc_start_phase_step != v_phase_step)) {
video_property_changed = 1;
/*pr_info("frame info register rdma write fail!\n");*/
}
}
if (likely(video_onoff_state != VIDEO_ENABLE_STATE_IDLE)) {
/* state change for video layer enable/disable */
spin_lock_irqsave(&video_onoff_lock, flags);
if (video_onoff_state == VIDEO_ENABLE_STATE_ON_REQ) {
/*
* the video layer is enabled one vsync later,assumming
* all registers are ready from RDMA.
*/
video_onoff_state = VIDEO_ENABLE_STATE_ON_PENDING;
} else if (video_onoff_state ==
VIDEO_ENABLE_STATE_ON_PENDING) {
vpp_misc_set |= VPP_VD1_PREBLEND |
VPP_VD1_POSTBLEND |
VPP_POSTBLEND_EN;
video_onoff_state = VIDEO_ENABLE_STATE_IDLE;
video_onoff_time = jiffies_to_msecs(jiffies);
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("VsyncEnableVideoLayer\n");
vpu_delay_work_flag |=
VPU_VIDEO_LAYER1_CHANGED;
force_flush = 1;
} else if (video_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) {
vpp_misc_set &= ~(VPP_VD1_PREBLEND |
VPP_VD1_POSTBLEND);
if (process_3d_type)
vpp_misc_set &= ~(VPP_VD2_PREBLEND |
VPP_VD2_POSTBLEND | VPP_PREBLEND_EN);
/*auto disable sr when video off*/
if (!is_meson_txl_cpu() &&
!is_meson_txlx_cpu()) {
VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0);
VSYNC_WR_MPEG_REG(VPP_SRSHARP1_CTRL, 0);
}
video_onoff_state = VIDEO_ENABLE_STATE_IDLE;
video_onoff_time = jiffies_to_msecs(jiffies);
vpu_delay_work_flag |=
VPU_VIDEO_LAYER1_CHANGED;
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("VsyncDisableVideoLayer\n");
video1_off_req = 1;
force_flush = 1;
}
spin_unlock_irqrestore(&video_onoff_lock, flags);
}
if (likely(video2_onoff_state != VIDEO_ENABLE_STATE_IDLE)) {
/* state change for video layer2 enable/disable */
spin_lock_irqsave(&video2_onoff_lock, flags);
if (video2_onoff_state == VIDEO_ENABLE_STATE_ON_REQ) {
/*
* the video layer 2
* is enabled one vsync later, assumming
* all registers are ready from RDMA.
*/
video2_onoff_state = VIDEO_ENABLE_STATE_ON_PENDING;
} else if (video2_onoff_state ==
VIDEO_ENABLE_STATE_ON_PENDING) {
if (is_dolby_vision_on())
vpp_misc_set &= ~(VPP_VD2_PREBLEND |
VPP_VD2_POSTBLEND | VPP_PREBLEND_EN);
else if (process_3d_type ||
(cur_dispbuf &&
(cur_dispbuf->type & VIDTYPE_MVC)))
vpp_misc_set |= VPP_VD2_PREBLEND |
VPP_PREBLEND_EN;
else if (!legacy_vpp)
vpp_misc_set |= VPP_VD2_POSTBLEND |
VPP_POSTBLEND_EN;
else
vpp_misc_set |= VPP_VD2_PREBLEND |
VPP_PREBLEND_EN;
#ifdef VIDEO_PIP
if (cur_pipbuf) {
vpp_misc_set &=
~(VPP_PREBLEND_EN | VPP_VD2_PREBLEND);
vpp_misc_set |= VPP_VD2_POSTBLEND;
}
#endif
/* g12a has no alpha overflow check in hardware */
if (!legacy_vpp)
vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT);
else
vpp_misc_set |= (0x1ff << VPP_VD2_ALPHA_BIT);
video2_onoff_state = VIDEO_ENABLE_STATE_IDLE;
video_onoff_time = jiffies_to_msecs(jiffies);
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("VsyncEnableVideoLayer2\n");
force_flush = 1;
} else if (video2_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) {
vpp_misc_set &= ~(VPP_VD2_PREBLEND |
VPP_VD2_POSTBLEND | VPP_PREBLEND_EN
| (0x1ff << VPP_VD2_ALPHA_BIT));
video2_onoff_state = VIDEO_ENABLE_STATE_IDLE;
video_onoff_time = jiffies_to_msecs(jiffies);
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("VsyncDisableVideoLayer2\n");
video2_off_req = 1;
force_flush = 1;
}
spin_unlock_irqrestore(&video2_onoff_lock, flags);
}
if ((video_global_output == 0)
|| black_threshold_check(0)) {
video_enabled = 0;
vpp_misc_set &= ~(VPP_VD1_PREBLEND |
VPP_VD2_PREBLEND |
VPP_VD2_POSTBLEND |
VPP_VD1_POSTBLEND |
VPP_PREBLEND_EN);
#ifdef VIDEO_PIP
/* should keep video2 display */
if (cur_pipbuf && video2_enabled)
vpp_misc_set |= VPP_VD2_POSTBLEND;
#endif
} else {
video_enabled = video_status_saved;
}
if (!video_enabled &&
(vpp_misc_set & VPP_VD1_POSTBLEND))
vpp_misc_set &= ~(VPP_VD1_PREBLEND |
VPP_VD1_POSTBLEND |
VPP_PREBLEND_EN);
#ifdef VIDEO_PIP
if ((pip_global_output == 0)
|| black_threshold_check(1)) {
video2_enabled = 0;
vpp_misc_set &= ~(VPP_VD2_PREBLEND |
VPP_VD2_POSTBLEND);
} else {
video2_enabled = video2_status_saved;
}
if (!video2_enabled &&
(vpp_misc_set & VPP_VD2_POSTBLEND))
vpp_misc_set &= ~(VPP_VD2_PREBLEND |
VPP_VD2_POSTBLEND);
#endif
if (!legacy_vpp) {
u32 set_value = 0;
force_flush |= vpp_zorder_check();
/* for sr core0, put it between prebld & pps as default */
if (cur_frame_par &&
(cur_frame_par->sr_core_support &
SUPER_CORE0_SUPPORT))
if (cur_frame_par->sr0_position)
vpp_misc_set |=
PREBLD_SR0_VD1_SCALER;
else
vpp_misc_set &=
~SR0_AFTER_DNLP;
else
vpp_misc_set |=
PREBLD_SR0_VD1_SCALER;
/* for sr core1, put it before post blend as default */
if (cur_frame_par &&
(cur_frame_par->sr_core_support &
SUPER_CORE1_SUPPORT))
if (cur_frame_par->sr1_position)
vpp_misc_set |=
DNLP_SR1_CM;
else
vpp_misc_set &=
~SR1_AFTER_POSTBLEN;
else
vpp_misc_set |=
DNLP_SR1_CM;
vpp_misc_set &=
((1 << 29) | VPP_CM_ENABLE |
(0x1ff << VPP_VD2_ALPHA_BIT) |
VPP_VD2_PREBLEND |
VPP_VD1_PREBLEND |
VPP_VD2_POSTBLEND |
VPP_VD1_POSTBLEND |
VPP_PREBLEND_EN |
VPP_POSTBLEND_EN |
0xf);
/* if vd2 is bottom layer, need remove alpha for vd2 */
if (((vpp_misc_set & VPP_VD1_POSTBLEND) == 0)
&& (vpp_misc_set & VPP_VD2_POSTBLEND)) {
vpp_misc_set &= ~(0x1ff << VPP_VD2_ALPHA_BIT);
vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT);
}
vpp_misc_save &=
((1 << 29) | VPP_CM_ENABLE |
(0x1ff << VPP_VD2_ALPHA_BIT) |
VPP_VD2_PREBLEND |
VPP_VD1_PREBLEND |
VPP_VD2_POSTBLEND |
VPP_VD1_POSTBLEND |
VPP_PREBLEND_EN |
VPP_POSTBLEND_EN |
0xf);
if ((vpp_misc_set != vpp_misc_save)
|| force_flush) {
u32 port_val[3] = {0, 0, 0};
u32 vd1_port, vd2_port, icnt;
u32 post_blend_reg[3] = {
VD1_BLEND_SRC_CTRL,
VD2_BLEND_SRC_CTRL,
OSD2_BLEND_SRC_CTRL
};
/* just reset the select port */
if ((glayer_info[0].cur_sel_port > 2)
|| (glayer_info[1].cur_sel_port > 2)) {
glayer_info[0].cur_sel_port = 0;
glayer_info[1].cur_sel_port = 1;
}
vd1_port = glayer_info[0].cur_sel_port;
vd2_port = glayer_info[1].cur_sel_port;
/* post bld premult*/
port_val[0] |= (1 << 16);
/* vd2 path sel */
if (vpp_misc_set & VPP_VD2_POSTBLEND)
port_val[1] |= (1 << 20);
else
port_val[1] &= ~(1 << 20);
/* osd2 path sel */
port_val[2] |= (1 << 20);
if (vpp_misc_set & VPP_VD1_POSTBLEND) {
/* post src */
port_val[vd1_port] |= (1 << 8);
port_val[0] |=
((1 << 4) | /* pre bld premult*/
(1 << 0)); /* pre bld src 1 */
} else
port_val[0] &= ~0xff;
if (vpp_misc_set & VPP_VD2_POSTBLEND)
/* post src */
port_val[vd2_port] |= (2 << 8);
else if (vpp_misc_set & VPP_VD2_PREBLEND)
port_val[1] |=
((1 << 4) | /* pre bld premult*/
(2 << 0)); /* pre bld src 1 */
for (icnt = 0; icnt < 3; icnt++)
VSYNC_WR_MPEG_REG(
post_blend_reg[icnt]
+ cur_dev->vpp_off,
port_val[icnt]);
set_value = vpp_misc_set;
set_value &=
((1 << 29) | VPP_CM_ENABLE |
(0x1ff << VPP_VD2_ALPHA_BIT) |
VPP_VD2_PREBLEND |
VPP_VD1_PREBLEND |
VPP_VD2_POSTBLEND |
VPP_VD1_POSTBLEND |
0xf);
if ((vpp_misc_set & VPP_VD2_PREBLEND)
&& (vpp_misc_set & VPP_VD1_PREBLEND))
set_value |= VPP_PREBLEND_EN;
if (bypass_cm)
set_value &= ~VPP_CM_ENABLE;
set_value |= VPP_POSTBLEND_EN;
VSYNC_WR_MPEG_REG(
VPP_MISC + cur_dev->vpp_off,
set_value);
}
} else if (vpp_misc_save != vpp_misc_set)
VSYNC_WR_MPEG_REG(
VPP_MISC + cur_dev->vpp_off,
vpp_misc_set);
/*vpp_misc_set maybe have same,but need off.*/
/* if vd1 off, disable vd2 also */
#ifdef VIDEO_PIP
if (video2_off_req && cur_pipbuf) {
if ((debug_flag & DEBUG_FLAG_BLACKOUT)
&& video2_off_req)
pr_info("VD2 AFBC off now.\n");
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0);
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG(
VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0);
}
if (cur_pipbuf && (cur_pipbuf == &local_pip))
cur_pipbuf = NULL;
} else if (!cur_pipbuf &&
(video2_off_req || video1_off_req)) {
if ((debug_flag & DEBUG_FLAG_BLACKOUT)
&& video2_off_req)
pr_info("VD2 AFBC off now.\n");
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0);
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG(
VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0);
}
last_el_w = 0;
last_el_status = 0;
if (cur_dispbuf2 && (cur_dispbuf2 == &vf_local2))
cur_dispbuf2 = NULL;
need_disable_vd2 = false;
}
#else
if (video2_off_req || video1_off_req) {
if ((debug_flag & DEBUG_FLAG_BLACKOUT)
&& video2_off_req)
pr_info("VD2 AFBC off now.\n");
VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
VSYNC_WR_MPEG_REG(
VD2_IF0_GEN_REG + cur_dev->viu_off, 0);
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG(
VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0);
}
last_el_w = 0;
last_el_status = 0;
if (cur_dispbuf2 && (cur_dispbuf2 == &vf_local2))
cur_dispbuf2 = NULL;
need_disable_vd2 = false;
}
#endif
if (video1_off_req) {
/*
* video layer off, swith off afbc,
* will enabled on new frame coming.
*/
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("AFBC off now.\n");
VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0);
VSYNC_WR_MPEG_REG(
VD1_IF0_GEN_REG + cur_dev->viu_off, 0);
if (!legacy_vpp) {
VSYNC_WR_MPEG_REG(
VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, 0);
}
if (is_dolby_vision_enable()) {
if (is_meson_txlx_stbmode() ||
is_meson_gxm())
VSYNC_WR_MPEG_REG_BITS(
VIU_MISC_CTRL1,
1, 16, 1); /* bypass core1 */
else if (cpu_after_eq(
MESON_CPU_MAJOR_ID_G12A))
VSYNC_WR_MPEG_REG_BITS(
DOLBY_PATH_CTRL, 1, 0, 1);
}
if (cur_dispbuf && (cur_dispbuf == &vf_local))
cur_dispbuf = NULL;
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
cur_rdma_buf = cur_dispbuf;
#ifdef VIDEO_PIP
pip_rdma_buf = cur_pipbuf;
#endif
/* vsync_rdma_config(); */
vsync_rdma_process();
if (debug_flag & DEBUG_FLAG_PRINT_RDMA) {
if (enable_rdma_log_count == 0)
enable_rdma_log(0);
}
rdma_enable_pre = is_vsync_rdma_enable();
#endif
if (timer_count > 50) {
timer_count = 0;
video_notify_flag |= VIDEO_NOTIFY_FRAME_WAIT;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if ((video_scaler_mode) && (scaler_pos_changed)) {
video_notify_flag |= VIDEO_NOTIFY_POS_CHANGED;
scaler_pos_changed = 0;
} else {
scaler_pos_changed = 0;
video_notify_flag &= ~VIDEO_NOTIFY_POS_CHANGED;
}
#endif
}
switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
case 0:
enc_line = (READ_VCBUS_REG(ENCL_INFO_READ) >> 16) & 0x1fff;
break;
case 1:
enc_line = (READ_VCBUS_REG(ENCI_INFO_READ) >> 16) & 0x1fff;
break;
case 2:
enc_line = (READ_VCBUS_REG(ENCP_INFO_READ) >> 16) & 0x1fff;
break;
case 3:
enc_line = (READ_VCBUS_REG(ENCT_INFO_READ) >> 16) & 0x1fff;
break;
}
if (enc_line > vsync_exit_line_max)
vsync_exit_line_max = enc_line;
#ifdef FIQ_VSYNC
if (video_notify_flag)
fiq_bridge_pulse_trigger(&vsync_fiq_bridge);
#else
if (video_notify_flag)
vsync_notify();
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) {
if (vpu_delay_work_flag)
schedule_work(&vpu_delay_work);
}
/* #endif */
return IRQ_HANDLED;
#endif
}
#ifdef FIQ_VSYNC
void vsync_fisr(void)
{
atomic_set(&video_inirq_flag, 1);
vsync_fisr_in();
atomic_set(&video_inirq_flag, 0);
}
#else
static irqreturn_t vsync_isr(int irq, void *dev_id)
{
irqreturn_t ret;
atomic_set(&video_inirq_flag, 1);
ret = vsync_isr_in(irq, dev_id);
atomic_set(&video_inirq_flag, 0);
return ret;
}
#endif
/*********************************************************
* FIQ Routines
*********************************************************/
static void vsync_fiq_up(void)
{
#ifdef FIQ_VSYNC
request_fiq(INT_VIU_VSYNC, &vsync_fisr);
#else
int r;
/*TODO irq */
r = request_irq(video_vsync, &vsync_isr,
IRQF_SHARED, "vsync", (void *)video_dev_id);
#ifdef CONFIG_MESON_TRUSTZONE
if (num_online_cpus() > 1)
irq_set_affinity(INT_VIU_VSYNC, cpumask_of(1));
#endif
#endif
}
static void vsync_fiq_down(void)
{
#ifdef FIQ_VSYNC
free_fiq(INT_VIU_VSYNC, &vsync_fisr);
#else
/*TODO irq */
free_irq(video_vsync, (void *)video_dev_id);
#endif
}
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
static void vsync2_fiq_up(void)
{
int r;
r = request_irq(INT_VIU2_VSYNC, &vsync_isr,
IRQF_SHARED, "vsync", (void *)video_dev_id2);
}
static void vsync2_fiq_down(void)
{
free_irq(INT_VIU2_VSYNC, (void *)video_dev_id2);
}
#endif
int get_curren_frame_para(int *top, int *left, int *bottom, int *right)
{
if (!cur_frame_par)
return -1;
*top = cur_frame_par->VPP_vd_start_lines_;
*left = cur_frame_par->VPP_hd_start_lines_;
*bottom = cur_frame_par->VPP_vd_end_lines_;
*right = cur_frame_par->VPP_hd_end_lines_;
return 0;
}
int get_current_vscale_skip_count(struct vframe_s *vf)
{
int ret = 0;
static struct vpp_frame_par_s frame_par;
vpp_set_filters(
&glayer_info[0],
vf, &frame_par, vinfo,
(is_dolby_vision_on() &&
is_dolby_vision_stb_mode()), 0);
ret = frame_par.vscale_skip_count;
if (cur_frame_par && (process_3d_type & MODE_3D_ENABLE))
ret |= (cur_frame_par->vpp_3d_mode<<8);
return ret;
}
int query_video_status(int type, int *value)
{
if (value == NULL)
return -1;
switch (type) {
case 0:
*value = trickmode_fffb;
break;
case 1:
*value = trickmode_i;
break;
default:
break;
}
return 0;
}
EXPORT_SYMBOL(query_video_status);
static void video_vf_unreg_provider(void)
{
ulong flags;
struct vframe_s *el_vf = NULL;
int keeped = 0;
new_frame_count = 0;
first_frame_toggled = 0;
videopeek = 0;
nopostvideostart = false;
atomic_set(&video_unreg_flag, 1);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
memset(&video_frame_detect, 0,
sizeof(struct video_frame_detect_s));
frame_detect_drop_count = 0;
frame_detect_receive_count = 0;
spin_lock_irqsave(&lock, flags);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
dispbuf_to_put_num = DISPBUF_TO_PUT_MAX;
while (dispbuf_to_put_num > 0) {
dispbuf_to_put_num--;
dispbuf_to_put[dispbuf_to_put_num] = NULL;
}
cur_rdma_buf = NULL;
#endif
if (cur_dispbuf) {
vf_local = *cur_dispbuf;
cur_dispbuf = &vf_local;
cur_dispbuf->video_angle = 0;
}
if (cur_dispbuf2)
need_disable_vd2 = true;
if (is_dolby_vision_enable()) {
if (cur_dispbuf2 == &vf_local2)
cur_dispbuf2 = NULL;
else if (cur_dispbuf2 != NULL) {
vf_local2 = *cur_dispbuf2;
el_vf = &vf_local2;
}
cur_dispbuf2 = NULL;
}
if (trickmode_fffb) {
atomic_set(&trickmode_framedone, 0);
to_notify_trick_wait = false;
}
vsync_pts_100 = 0;
vsync_pts_112 = 0;
vsync_pts_125 = 0;
vsync_freerun = 0;
vsync_pts_align = 0;
vsync_pts_aligned = false;
#ifdef VIDEO_PIP
if (pip_loop) {
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf_to_put = NULL;
pip_rdma_buf = NULL;
#endif
if (cur_pipbuf) {
local_pip = *cur_pipbuf;
cur_pipbuf = &local_pip;
cur_pipbuf->video_angle = 0;
}
pip_frame_count = 0;
}
#endif
spin_unlock_irqrestore(&lock, flags);
#ifdef VIDEO_PIP
if (pip_loop) {
disable_videopip = VIDEO_DISABLE_FORNEXT;
DisableVideoLayer2();
}
#endif
if (blackout | force_blackout) {
safe_disble_videolayer();
try_free_keep_video(1);
}
#ifdef CONFIG_GE2D_KEEP_FRAME
if (cur_dispbuf) {
/* TODO: mod gate */
/* switch_mod_gate_by_name("ge2d", 1); */
keeped = vf_keep_current(cur_dispbuf, el_vf);
/* TODO: mod gate */
/* switch_mod_gate_by_name("ge2d", 0); */
}
if ((hdmi_in_onvideo == 0) && (video_start_post)) {
tsync_avevent(VIDEO_STOP, 0);
video_start_post = false;
}
#else
/* if (!trickmode_fffb) */
if (cur_dispbuf)
keeped = vf_keep_current(cur_dispbuf, el_vf);
if ((hdmi_in_onvideo == 0) && (video_start_post)) {
tsync_avevent(VIDEO_STOP, 0);
video_start_post = false;
}
#endif
if (keeped < 0) {/*keep failed.*/
pr_info("video keep failed, disable video now!\n");
safe_disble_videolayer();
try_free_keep_video(1);
}
atomic_set(&video_unreg_flag, 0);
pr_info("VD1 AFBC 0x%x.\n", READ_VCBUS_REG(AFBC_ENABLE));
enable_video_discontinue_report = 1;
show_first_picture = false;
show_first_frame_nosync = false;
#ifdef PTS_LOGGING
{
int pattern;
/* Print what we have right now*/
if (pts_pattern_detected >= PTS_32_PATTERN &&
pts_pattern_detected < PTS_MAX_NUM_PATTERNS) {
pr_info("pattern detected = %d, pts_enter_pattern_cnt =%d, pts_exit_pattern_cnt =%d",
pts_pattern_detected,
pts_pattern_enter_cnt[pts_pattern_detected],
pts_pattern_exit_cnt[pts_pattern_detected]);
}
/* Reset all metrics now*/
for (pattern = 0; pattern < PTS_MAX_NUM_PATTERNS; pattern++) {
pts_pattern[pattern] = 0;
pts_pattern_exit_cnt[pattern] = 0;
pts_pattern_enter_cnt[pattern] = 0;
}
/* Reset 4:1 data*/
memset(&pts_41_pattern_sink[0], 0, PTS_41_PATTERN_SINK_MAX);
pts_pattern_detected = -1;
pre_pts_trace = 0;
pts_escape_vsync = 0;
}
#endif
}
static void video_vf_light_unreg_provider(int need_keep_frame)
{
ulong flags;
if (need_keep_frame) {
/* wait for the end of the last toggled frame*/
atomic_set(&video_unreg_flag, 1);
while (atomic_read(&video_inirq_flag) > 0)
schedule();
}
spin_lock_irqsave(&lock, flags);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
dispbuf_to_put_num = DISPBUF_TO_PUT_MAX;
while (dispbuf_to_put_num > 0) {
dispbuf_to_put_num--;
dispbuf_to_put[dispbuf_to_put_num] = NULL;
}
cur_rdma_buf = NULL;
#endif
if (cur_dispbuf) {
vf_local = *cur_dispbuf;
cur_dispbuf = &vf_local;
}
spin_unlock_irqrestore(&lock, flags);
if (need_keep_frame) {
/* keep the last toggled frame*/
if (cur_dispbuf) {
unsigned int result;
result = vf_keep_current(cur_dispbuf, NULL);
if (result == 0)
pr_info("%s: keep cur_disbuf failed\n",
__func__);
}
atomic_set(&video_unreg_flag, 0);
}
}
static int get_display_info(void *data)
{
s32 w, h, x, y;
struct vdisplay_info_s *info_para = (struct vdisplay_info_s *)data;
const struct vinfo_s *info = get_current_vinfo();
struct disp_info_s *layer = &glayer_info[0];
if ((!cur_frame_par) || (!info))
return -1;
x = layer->layer_left;
y = layer->layer_top;
w = layer->layer_width;
h = layer->layer_height;
if ((w == 0) || (w > info->width))
w = info->width;
if ((h == 0) || (h > info->height))
h = info->height;
info_para->frame_hd_start_lines_ = cur_frame_par->VPP_hd_start_lines_;
info_para->frame_hd_end_lines_ = cur_frame_par->VPP_hd_end_lines_;
info_para->frame_vd_start_lines_ = cur_frame_par->VPP_vd_start_lines_;
info_para->frame_vd_end_lines_ = cur_frame_par->VPP_vd_end_lines_;
info_para->display_hsc_startp = cur_frame_par->VPP_hsc_startp - x;
info_para->display_hsc_endp =
cur_frame_par->VPP_hsc_endp + (info->width - x - w);
info_para->display_vsc_startp = cur_frame_par->VPP_vsc_startp - y;
info_para->display_vsc_endp =
cur_frame_par->VPP_vsc_endp + (info->height - y - h);
info_para->screen_vd_h_start_ =
cur_frame_par->VPP_post_blend_vd_h_start_;
info_para->screen_vd_h_end_ =
cur_frame_par->VPP_post_blend_vd_h_end_;
info_para->screen_vd_v_start_ =
cur_frame_par->VPP_post_blend_vd_v_start_;
info_para->screen_vd_v_end_ = cur_frame_par->VPP_post_blend_vd_v_end_;
return 0;
}
#if ENABLE_UPDATE_HDR_FROM_USER
void init_hdr_info(void)
{
unsigned long flags;
spin_lock_irqsave(&omx_hdr_lock, flags);
has_hdr_info = false;
memset(&vf_hdr, 0, sizeof(vf_hdr));
spin_unlock_irqrestore(&omx_hdr_lock, flags);
}
#endif
static int video_receiver_event_fun(int type, void *data, void *private_data)
{
#ifdef CONFIG_AM_VIDEO2
char *provider_name;
#endif
if (type == VFRAME_EVENT_PROVIDER_UNREG) {
video_vf_unreg_provider();
#ifdef CONFIG_AM_VIDEO2
set_clone_frame_rate(android_clone_rate, 200);
#endif
drop_frame_count = 0;
receive_frame_count = 0;
display_frame_count = 0;
frame_render_ready = 0;
} else if (type == VFRAME_EVENT_PROVIDER_RESET) {
video_vf_light_unreg_provider(1);
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG)
video_vf_light_unreg_provider(0);
else if (type == VFRAME_EVENT_PROVIDER_REG) {
enable_video_discontinue_report = 1;
drop_frame_count = 0;
frame_render_ready = 0;
receive_frame_count = 0;
display_frame_count = 0;
video_drop_vf_cnt = 0;
video_repeat_vf_cnt = 0;
omx_run = false;
omx_pts_set_from_hwc_count = 0;
omx_check_previous_session = true;
omx_need_drop_frame_num = 0;
omx_drop_done = false;
omx_pts_set_index = 0;
//init_hdr_info();
#ifdef CONFIG_AM_VIDEO2
provider_name = (char *)data;
if (strncmp(provider_name, "decoder", 7) == 0
|| strncmp(provider_name, "ppmgr", 5) == 0
|| strncmp(provider_name, "deinterlace", 11) == 0
|| strncmp(provider_name, "d2d3", 11) == 0) {
set_clone_frame_rate(noneseamless_play_clone_rate, 0);
set_clone_frame_rate(video_play_clone_rate, 100);
}
#endif
/*notify di 3d mode is frame*/
/*alternative mode,passing two buffer in one frame */
if (platform_type == 1) {
if ((process_3d_type & MODE_3D_FA) &&
!cur_dispbuf->trans_fmt)
vf_notify_receiver_by_name("deinterlace",
VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE,
(void *)1);
}
video_vf_light_unreg_provider(0);
} else if (type == VFRAME_EVENT_PROVIDER_FORCE_BLACKOUT) {
force_blackout = 1;
if (debug_flag & DEBUG_FLAG_BLACKOUT) {
pr_info("%s VFRAME_EVENT_PROVIDER_FORCE_BLACKOUT\n",
__func__);
}
} else if (type == VFRAME_EVENT_PROVIDER_FR_HINT) {
#ifdef CONFIG_AM_VOUT
if ((data != NULL) && (video_seek_flag == 0)) {
set_vframe_rate_hint((unsigned long)data);
omx_pts_dv_upper = DUR2PTS((unsigned long)data) * 3 / 2;
omx_pts_dv_lower = 0 - DUR2PTS((unsigned long)data);
}
#endif
} else if (type == VFRAME_EVENT_PROVIDER_FR_END_HINT) {
#ifdef CONFIG_AM_VOUT
if (video_seek_flag == 0) {
set_vframe_rate_end_hint();
omx_pts_dv_upper = OMX_PTS_DV_DEFAULT_UPPER;
omx_pts_dv_lower = OMX_PTS_DV_DEFAULT_LOWER;
}
#endif
} else if (type == VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO) {
get_display_info(data);
} else if (type == VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED)
video_property_changed = 1;
return 0;
}
#ifdef VIDEO_PIP
static void pip_vf_unreg_provider(void)
{
ulong flags;
int keeped = 0;
/* atomic_set(&video_unreg_flag, 1); */
while (atomic_read(&video_inirq_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf_to_put = NULL;
pip_rdma_buf = NULL;
#endif
if (cur_pipbuf) {
local_pip = *cur_pipbuf;
cur_pipbuf = &local_pip;
cur_pipbuf->video_angle = 0;
}
pip_frame_count = 0;
spin_unlock_irqrestore(&lock, flags);
if (blackout_pip | force_blackout) {
safe_disble_videolayer2();
try_free_keep_videopip(1);
}
if (cur_pipbuf)
keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL);
if (keeped < 0) {/*keep failed.*/
pr_info("videopip keep failed, disable video now!\n");
safe_disble_videolayer2();
try_free_keep_videopip(1);
}
/*disable_videopip = VIDEO_DISABLE_FORNEXT;*/
/*DisableVideoLayer2();*/
}
static void pip_vf_light_unreg_provider(int need_keep_frame)
{
ulong flags;
spin_lock_irqsave(&lock, flags);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
pipbuf_to_put = NULL;
pip_rdma_buf = NULL;
#endif
if (cur_pipbuf) {
local_pip = *cur_pipbuf;
cur_pipbuf = &local_pip;
}
spin_unlock_irqrestore(&lock, flags);
if (need_keep_frame) {
if (cur_pipbuf) {
vf_keep_pip_current_locked(cur_pipbuf, NULL);
}
}
}
static int pip_receiver_event_fun(
int type, void *data, void *private_data)
{
if (type == VFRAME_EVENT_PROVIDER_UNREG)
pip_vf_unreg_provider();
else if (type == VFRAME_EVENT_PROVIDER_RESET)
pip_vf_light_unreg_provider(1);
else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG)
pip_vf_light_unreg_provider(0);
else if (type == VFRAME_EVENT_PROVIDER_REG)
pip_vf_light_unreg_provider(0);
return 0;
}
#endif
unsigned int get_post_canvas(void)
{
return post_canvas;
}
EXPORT_SYMBOL(get_post_canvas);
u32 get_blackout_policy(void)
{
return blackout | force_blackout;
}
EXPORT_SYMBOL(get_blackout_policy);
u32 set_blackout_policy(int policy)
{
blackout = policy;
return 0;
}
EXPORT_SYMBOL(set_blackout_policy);
u32 get_blackout_pip_policy(void)
{
return blackout_pip | force_blackout;
}
EXPORT_SYMBOL(get_blackout_pip_policy);
u32 set_blackout_pip_policy(int policy)
{
blackout_pip = policy;
return 0;
}
EXPORT_SYMBOL(set_blackout_pip_policy);
u8 is_vpp_postblend(void)
{
if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_VD1_POSTBLEND)
return 1;
return 0;
}
EXPORT_SYMBOL(is_vpp_postblend);
void pause_video(unsigned char pause_flag)
{
atomic_set(&video_pause_flag, pause_flag ? 1 : 0);
}
EXPORT_SYMBOL(pause_video);
/*********************************************************
* Utilities
*********************************************************/
int _video_set_disable(u32 val)
{
if (val > VIDEO_DISABLE_FORNEXT)
return -EINVAL;
disable_video = val;
if (disable_video != VIDEO_DISABLE_NONE) {
safe_disble_videolayer();
if ((disable_video == VIDEO_DISABLE_FORNEXT) && cur_dispbuf
&& (cur_dispbuf != &vf_local))
video_property_changed = 1;
try_free_keep_video(0);
} else {
if (cur_dispbuf && (cur_dispbuf != &vf_local)) {
EnableVideoLayer();
video_property_changed = 1;
}
}
return 0;
}
static void _set_video_crop(
struct disp_info_s *layer, int *p)
{
int last_l, last_r, last_t, last_b;
int new_l, new_r, new_t, new_b;
if (!layer)
return;
last_t = layer->crop_top;
last_l = layer->crop_left;
last_b = layer->crop_bottom;
last_r = layer->crop_right;
new_t = layer->crop_top = p[0];
new_l = layer->crop_left = p[1];
new_b = layer->crop_bottom = p[2];
new_r = layer->crop_right = p[3];
if ((new_t != last_t) || (new_l != last_l)
|| (new_b != last_b) || (new_r != last_r)) {
if (layer->layer_id == 0)
video_property_changed = 1;
#ifdef VIDEO_PIP
else if (layer->layer_id == 1)
pip_property_changed = 1;
#endif
}
}
static void _set_video_window(
struct disp_info_s *layer, int *p)
{
int w, h;
int *parsed = p;
int last_x, last_y, last_w, last_h;
int new_x, new_y, new_w, new_h;
#ifdef TV_REVERSE
int temp, temp1;
const struct vinfo_s *info = get_current_vinfo();
#endif
if (!layer)
return;
#ifdef TV_REVERSE
/* FIXME: use layer info */
if (reverse) {
temp = parsed[0];
temp1 = parsed[1];
parsed[0] = info->width - parsed[2] - 1;
parsed[1] = info->height - parsed[3] - 1;
parsed[2] = info->width - temp - 1;
parsed[3] = info->height - temp1 - 1;
}
#endif
last_x = layer->layer_left;
last_y = layer->layer_top;
last_w = layer->layer_width;
last_h = layer->layer_height;
w = parsed[2] - parsed[0] + 1;
h = parsed[3] - parsed[1] + 1;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (video_scaler_mode) {
if ((w == 1) && (h == 1)) {
w = 0;
h = 0;
}
if ((content_left != parsed[0]) || (content_top != parsed[1])
|| (content_w != w) || (content_h != h))
scaler_pos_changed = 1;
content_left = parsed[0];
content_top = parsed[1];
content_w = w;
content_h = h;
/* video_notify_flag =*/
/*video_notify_flag|VIDEO_NOTIFY_POS_CHANGED; */
} else
#endif
{
if ((w > 0) && (h > 0)) {
if ((w == 1) && (h == 1)) {
w = 0;
h = 0;
}
layer->layer_left = parsed[0];
layer->layer_top = parsed[1];
layer->layer_width = w;
layer->layer_height = h;
}
}
new_x = layer->layer_left;
new_y = layer->layer_top;
new_w = layer->layer_width;
new_h = layer->layer_height;
if ((last_x != new_x) || (last_y != new_y)
|| (last_w != new_w) || (last_h != new_h)) {
if (layer->layer_id == 0)
video_property_changed = 1;
#ifdef VIDEO_PIP
else if (layer->layer_id == 1)
pip_property_changed = 1;
#endif
}
}
#if ENABLE_UPDATE_HDR_FROM_USER
static void config_hdr_info(const struct vframe_master_display_colour_s p)
{
struct vframe_master_display_colour_s tmp = {0};
bool valid_hdr = false;
unsigned long flags;
tmp.present_flag = p.present_flag;
if (tmp.present_flag == 1) {
tmp = p;
if (tmp.primaries[0][0] == 0 &&
tmp.primaries[0][1] == 0 &&
tmp.primaries[1][0] == 0 &&
tmp.primaries[1][1] == 0 &&
tmp.primaries[2][0] == 0 &&
tmp.primaries[2][1] == 0 &&
tmp.white_point[0] == 0 &&
tmp.white_point[1] == 0 &&
tmp.luminance[0] == 0 &&
tmp.luminance[1] == 0 &&
tmp.content_light_level.max_content == 0 &&
tmp.content_light_level.max_pic_average == 0) {
valid_hdr = false;
} else {
valid_hdr = true;
}
}
spin_lock_irqsave(&omx_hdr_lock, flags);
vf_hdr = tmp;
has_hdr_info = valid_hdr;
spin_unlock_irqrestore(&omx_hdr_lock, flags);
pr_debug("has_hdr_info %d\n", has_hdr_info);
}
#endif
static void set_omx_pts(u32 *p)
{
u32 tmp_pts = p[0];
/*u32 vision = p[1];*/
u32 set_from_hwc = p[2];
u32 frame_num = p[3];
u32 not_reset = p[4];
u32 session = p[5];
unsigned int try_cnt = 0x1000;
mutex_lock(&omx_mutex);
if (omx_pts_set_index < frame_num)
omx_pts_set_index = frame_num;
if (omx_check_previous_session) {
if (session != omx_cur_session) {
omx_cur_session = session;
omx_check_previous_session = false;
} else {
mutex_unlock(&omx_mutex);
pr_info("check session return: tmp_pts %d"
"session=0x%x\n", tmp_pts, omx_cur_session);
return;
}
}
if (debug_flag & DEBUG_FLAG_PTS_TRACE)
pr_info("[set_omx_pts]tmp_pts:%d, set_from_hwc:%d,frame_num=%d, not_reset=%d\n",
tmp_pts, set_from_hwc, frame_num, not_reset);
if (not_reset == 0)
omx_pts = tmp_pts;
/* kodi may render first frame, then drop dozens of frames */
if (set_from_hwc == 0 && omx_run == true && frame_num <= 2
&& not_reset == 0) {
pr_info("reset omx_run to false.\n");
omx_run = false;
}
if (set_from_hwc == 1) {
if (!omx_run) {
omx_need_drop_frame_num =
frame_num > 0 ? frame_num-1 : 0;
if (omx_need_drop_frame_num == 0)
omx_drop_done = true;
pr_info("omx_need_drop_frame_num %d\n",
omx_need_drop_frame_num);
}
omx_run = true;
if (omx_pts_set_from_hwc_count < OMX_MAX_COUNT_RESET_SYSTEMTIME)
omx_pts_set_from_hwc_count++;
} else if (set_from_hwc == 0 && !omx_run) {
struct vframe_s *vf = NULL;
u32 donot_drop = 0;
while (try_cnt--) {
vf = vf_peek(RECEIVER_NAME);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (is_dolby_vision_enable()
&& vf && is_dovi_frame(vf)) {
pr_info("set_omx_pts ignore the omx %d frames drop for dv frame\n",
frame_num);
donot_drop = 1;
break;
}
#endif
if (vf) {
pr_debug("drop frame_num=%d, vf->omx_index=%d\n",
frame_num, vf->omx_index);
if (frame_num >= vf->omx_index) {
vf = vf_get(RECEIVER_NAME);
if (vf)
vf_put(vf, RECEIVER_NAME);
} else
break;
} else
break;
}
if (donot_drop && omx_pts_set_from_hwc_count > 0) {
pr_info("reset omx_run to true.\n");
omx_run = true;
}
}
mutex_unlock(&omx_mutex);
}
static int alloc_layer(u32 layer_id)
{
int ret = -EINVAL;
if (layer_id == 0) {
if (layer_cap & LAYER0_BUSY) {
ret = -EBUSY;
} else if (layer_cap & LAYER0_AVAIL) {
ret = 0;
layer_cap |= LAYER0_BUSY;
}
} else if (layer_id == 1) {
if (layer_cap & LAYER1_BUSY) {
ret = -EBUSY;
} else if (layer_cap & LAYER1_AVAIL) {
ret = 0;
layer_cap |= LAYER1_BUSY;
}
}
return ret;
}
static int free_layer(u32 layer_id)
{
int ret = -EINVAL;
if (layer_id == 0) {
if ((layer_cap & LAYER0_BUSY)
&& (layer_cap & LAYER0_AVAIL)) {
ret = 0;
layer_cap &= ~LAYER0_BUSY;
}
} else if (layer_id == 1) {
if ((layer_cap & LAYER1_BUSY)
&& (layer_cap & LAYER1_AVAIL)) {
ret = 0;
layer_cap &= ~LAYER1_BUSY;
}
}
return ret;
}
/*********************************************************
* /dev/amvideo APIs
********************************************************
*/
static int amvideo_open(struct inode *inode, struct file *file)
{
file->private_data = NULL;
return 0;
}
static int amvideo_poll_open(struct inode *inode, struct file *file)
{
file->private_data = NULL;
return 0;
}
static int amvideo_release(struct inode *inode, struct file *file)
{
file->private_data = NULL;
return 0;
}
static int amvideo_poll_release(struct inode *inode, struct file *file)
{
file->private_data = NULL;
return 0;
}
static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
{
long ret = 0;
void __user *argp = (void __user *)arg;
struct disp_info_s *layer = &glayer_info[0];
u32 layer_id;
switch (cmd) {
case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE:
case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE:
case AMSTREAM_IOC_GET_VIDEOPIP_AXIS:
case AMSTREAM_IOC_SET_VIDEOPIP_AXIS:
case AMSTREAM_IOC_GET_VIDEOPIP_CROP:
case AMSTREAM_IOC_SET_VIDEOPIP_CROP:
case AMSTREAM_IOC_GET_PIP_SCREEN_MODE:
case AMSTREAM_IOC_SET_PIP_SCREEN_MODE:
case AMSTREAM_IOC_GET_PIP_ZORDER:
case AMSTREAM_IOC_SET_PIP_ZORDER:
layer = &glayer_info[1];
break;
default:
break;
}
if (file->private_data)
layer = (struct disp_info_s *)file->private_data;
switch (cmd) {
case AMSTREAM_IOC_SET_HDR_INFO:{
#if ENABLE_UPDATE_HDR_FROM_USER
struct vframe_master_display_colour_s tmp;
if (copy_from_user(&tmp, argp, sizeof(tmp)) == 0)
config_hdr_info(tmp);
#endif
}
break;
case AMSTREAM_IOC_SET_OMX_VPTS:{
u32 pts[6];
if (copy_from_user(pts, argp, sizeof(pts)) == 0)
set_omx_pts(pts);
}
break;
case AMSTREAM_IOC_GET_OMX_VPTS:
put_user(omx_pts, (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_OMX_VERSION:
put_user(omx_version, (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_OMX_INFO:
put_user(omx_info, (u32 __user *)argp);
break;
case AMSTREAM_IOC_TRICKMODE:
if (arg == TRICKMODE_I)
trickmode_i = 1;
else if (arg == TRICKMODE_FFFB)
trickmode_fffb = 1;
else {
trickmode_i = 0;
trickmode_fffb = 0;
}
to_notify_trick_wait = false;
atomic_set(&trickmode_framedone, 0);
tsync_trick_mode(trickmode_fffb);
break;
case AMSTREAM_IOC_TRICK_STAT:
put_user(atomic_read(&trickmode_framedone),
(u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_TRICK_VPTS:
put_user(trickmode_vpts, (u32 __user *)argp);
break;
case AMSTREAM_IOC_VPAUSE:
tsync_avevent(VIDEO_PAUSE, arg);
break;
case AMSTREAM_IOC_AVTHRESH:
tsync_set_avthresh(arg);
break;
case AMSTREAM_IOC_SYNCTHRESH:
tsync_set_syncthresh(arg);
break;
case AMSTREAM_IOC_SYNCENABLE:
tsync_set_enable(arg);
break;
case AMSTREAM_IOC_SET_SYNC_ADISCON:
tsync_set_sync_adiscont(arg);
break;
case AMSTREAM_IOC_SET_SYNC_VDISCON:
tsync_set_sync_vdiscont(arg);
break;
case AMSTREAM_IOC_GET_SYNC_ADISCON:
put_user(tsync_get_sync_adiscont(), (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_SYNC_VDISCON:
put_user(tsync_get_sync_vdiscont(), (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_SYNC_ADISCON_DIFF:
put_user(tsync_get_sync_adiscont_diff(), (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_SYNC_VDISCON_DIFF:
put_user(tsync_get_sync_vdiscont_diff(), (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_SYNC_ADISCON_DIFF:
tsync_set_sync_adiscont_diff(arg);
break;
case AMSTREAM_IOC_SET_SYNC_VDISCON_DIFF:
tsync_set_sync_vdiscont_diff(arg);
break;
case AMSTREAM_IOC_VF_STATUS:{
struct vframe_states vfsta;
struct vframe_states states;
video_vf_get_states(&vfsta);
states.vf_pool_size = vfsta.vf_pool_size;
states.buf_avail_num = vfsta.buf_avail_num;
states.buf_free_num = vfsta.buf_free_num;
states.buf_recycle_num = vfsta.buf_recycle_num;
if (copy_to_user(argp, &states, sizeof(states)))
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE:
put_user(disable_videopip, (u32 __user *)argp);
break;
case AMSTREAM_IOC_GET_VIDEO_DISABLE:
put_user(disable_video, (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE:
{
u32 val;
if (copy_from_user(&val, argp, sizeof(u32)) == 0)
ret = _videopip_set_disable(val);
else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_SET_VIDEO_DISABLE:
{
u32 val;
if (copy_from_user(&val, argp, sizeof(u32)) == 0) {
ret = _video_set_disable(val);
} else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT:
put_user(enable_video_discontinue_report, (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT:
enable_video_discontinue_report = (arg == 0) ? 0 : 1;
break;
case AMSTREAM_IOC_GET_VIDEOPIP_AXIS:
case AMSTREAM_IOC_GET_VIDEO_AXIS:
{
int axis[4];
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (video_scaler_mode && (layer->layer_id == 0)) {
axis[0] = content_left;
axis[1] = content_top;
axis[2] = content_w;
axis[3] = content_h;
} else
#endif
{
axis[0] = layer->layer_left;
axis[1] = layer->layer_top;
axis[2] = layer->layer_width;
axis[3] = layer->layer_height;
}
axis[2] = axis[0] + axis[2] - 1;
axis[3] = axis[1] + axis[3] - 1;
if (copy_to_user(argp, &axis[0], sizeof(axis)) != 0)
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_SET_VIDEOPIP_AXIS:
case AMSTREAM_IOC_SET_VIDEO_AXIS:
{
int axis[4];
if (copy_from_user(axis, argp, sizeof(axis)) == 0)
_set_video_window(layer, axis);
else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_GET_VIDEOPIP_CROP:
case AMSTREAM_IOC_GET_VIDEO_CROP:
{
int crop[4];
{
crop[0] = layer->crop_top;
crop[1] = layer->crop_left;
crop[2] = layer->crop_bottom;
crop[3] = layer->crop_right;
}
if (copy_to_user(argp, &crop[0], sizeof(crop)) != 0)
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_SET_VIDEOPIP_CROP:
case AMSTREAM_IOC_SET_VIDEO_CROP:
{
int crop[4];
if (copy_from_user(crop, argp, sizeof(crop)) == 0)
_set_video_crop(layer, crop);
else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_GET_PIP_SCREEN_MODE:
case AMSTREAM_IOC_GET_SCREEN_MODE:
if (copy_to_user(argp, &layer->wide_mode, sizeof(u32)) != 0)
ret = -EFAULT;
break;
case AMSTREAM_IOC_SET_PIP_SCREEN_MODE:
case AMSTREAM_IOC_SET_SCREEN_MODE:
{
u32 mode;
if (copy_from_user(&mode, argp, sizeof(u32)) == 0) {
if (mode >= VIDEO_WIDEOPTION_MAX)
ret = -EINVAL;
else if (mode != layer->wide_mode) {
layer->wide_mode = mode;
if (layer->layer_id == 0)
video_property_changed = 1;
#ifdef VIDEO_PIP
else if (layer->layer_id == 1)
pip_property_changed = 1;
#endif
}
} else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_GET_BLACKOUT_POLICY:
if (copy_to_user(argp, &blackout, sizeof(u32)) != 0)
ret = -EFAULT;
break;
case AMSTREAM_IOC_SET_BLACKOUT_POLICY:{
u32 mode;
if (copy_from_user(&mode, argp, sizeof(u32)) == 0) {
if (mode > 2)
ret = -EINVAL;
else
blackout = mode;
} else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY:
if (copy_to_user(argp, &blackout_pip, sizeof(u32)) != 0)
ret = -EFAULT;
break;
case AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY:{
u32 mode;
if (copy_from_user(&mode, argp, sizeof(u32)) == 0) {
if (mode > 2)
ret = -EINVAL;
else
blackout_pip = mode;
} else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_CLEAR_VBUF:{
unsigned long flags;
while (atomic_read(&video_inirq_flag) > 0 ||
atomic_read(&video_unreg_flag) > 0)
schedule();
spin_lock_irqsave(&lock, flags);
cur_dispbuf = NULL;
spin_unlock_irqrestore(&lock, flags);
}
break;
case AMSTREAM_IOC_CLEAR_VIDEO:
if (blackout)
safe_disble_videolayer();
break;
case AMSTREAM_IOC_CLEAR_PIP_VBUF:{
unsigned long flags;
spin_lock_irqsave(&lock, flags);
cur_pipbuf = NULL;
spin_unlock_irqrestore(&lock, flags);
}
break;
case AMSTREAM_IOC_CLEAR_VIDEOPIP:
safe_disble_videolayer2();
break;
case AMSTREAM_IOC_SET_FREERUN_MODE:
if (arg > FREERUN_DUR)
ret = -EFAULT;
else
freerun_mode = arg;
break;
case AMSTREAM_IOC_GET_FREERUN_MODE:
put_user(freerun_mode, (u32 __user *)argp);
break;
case AMSTREAM_IOC_DISABLE_SLOW_SYNC:
if (arg)
disable_slow_sync = 1;
else
disable_slow_sync = 0;
break;
/*
***************************************************************
*3d process ioctl
****************************************************************
*/
case AMSTREAM_IOC_SET_3D_TYPE:
{
#ifdef TV_3D_FUNCTION_OPEN
unsigned int set_3d =
VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE;
unsigned int type = (unsigned int)arg;
if (type != process_3d_type) {
process_3d_type = type;
if (mvc_flag)
process_3d_type |= MODE_3D_MVC;
video_property_changed = 1;
if ((process_3d_type & MODE_3D_FA)
&& cur_dispbuf
&& !cur_dispbuf->trans_fmt)
/*notify di 3d mode is frame*/
/*alternative mode,passing two*/
/*buffer in one frame */
vf_notify_receiver_by_name(
"deinterlace",
set_3d,
(void *)1);
else
vf_notify_receiver_by_name(
"deinterlace",
set_3d,
(void *)0);
}
#endif
break;
}
case AMSTREAM_IOC_GET_3D_TYPE:
#ifdef TV_3D_FUNCTION_OPEN
put_user(process_3d_type, (u32 __user *)argp);
#endif
break;
case AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE:
#ifdef TV_3D_FUNCTION_OPEN
{
int source_video_3d_type = VPP_3D_MODE_NULL;
if (!cur_frame_par)
source_video_3d_type =
VPP_3D_MODE_NULL;
else
get_vpp_3d_mode(process_3d_type,
cur_frame_par->trans_fmt, &source_video_3d_type);
put_user(source_video_3d_type, (u32 __user *)argp);
}
#endif
break;
case AMSTREAM_IOC_SET_VSYNC_UPINT:
vsync_pts_inc_upint = arg;
break;
case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR:
put_user(vsync_slow_factor, (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR:
vsync_slow_factor = arg;
break;
case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT:
if (layer->layer_id == 0) {
if (arg != 0)
video_global_output = 1;
else
video_global_output = 0;
}
#ifdef VIDEO_PIP
else if (layer->layer_id == 1) {
if (arg != 0)
pip_global_output = 1;
else
pip_global_output = 0;
}
#endif
break;
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT:
if (layer->layer_id == 0)
put_user(video_global_output, (u32 __user *)argp);
#ifdef VIDEO_PIP
else if (layer->layer_id == 1)
put_user(pip_global_output, (u32 __user *)argp);
#endif
break;
case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: {
u32 vsync_duration;
u32 video_onoff_diff = 0;
vsync_duration = vsync_pts_inc / 90;
video_onoff_diff =
jiffies_to_msecs(jiffies) - video_onoff_time;
if (video_onoff_state == VIDEO_ENABLE_STATE_IDLE) {
/* wait until 5ms after next vsync */
msleep(video_onoff_diff < vsync_duration
? vsync_duration - video_onoff_diff + 5
: 0);
}
put_user(video_onoff_state, (u32 __user *)argp);
break;
}
case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED:
put_user(first_frame_toggled, (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_VIDEOPEEK:
videopeek = true;
nopostvideostart = true;
break;
case AMSTREAM_IOC_GET_PIP_ZORDER:
case AMSTREAM_IOC_GET_ZORDER:
put_user(layer->zorder, (u32 __user *)argp);
break;
case AMSTREAM_IOC_SET_PIP_ZORDER:
case AMSTREAM_IOC_SET_ZORDER:{
u32 zorder, new_prop = 0;
if (copy_from_user(&zorder, argp, sizeof(u32)) == 0) {
if (layer->zorder != zorder)
new_prop = 1;
layer->zorder = zorder;
if ((layer->layer_id == 0) && new_prop)
video_property_changed = 1;
#ifdef VIDEO_PIP
else if ((layer->layer_id == 1) && new_prop)
pip_property_changed = 1;
#endif
} else
ret = -EFAULT;
}
break;
case AMSTREAM_IOC_QUERY_LAYER:
mutex_lock(&video_layer_mutex);
put_user(layer_cap, (u32 __user *)argp);
mutex_unlock(&video_layer_mutex);
ret = 0;
break;
case AMSTREAM_IOC_ALLOC_LAYER:
if (copy_from_user(&layer_id, argp, sizeof(u32)) == 0) {
if (layer_id >= MAX_VD_LAYERS) {
ret = -EINVAL;
} else {
mutex_lock(&video_layer_mutex);
if (file->private_data) {
ret = -EBUSY;
} else {
ret = alloc_layer(layer_id);
if (!ret)
file->private_data =
(void *)&glayer_info[layer_id];
}
mutex_unlock(&video_layer_mutex);
}
} else
ret = -EFAULT;
break;
case AMSTREAM_IOC_FREE_LAYER:
mutex_lock(&video_layer_mutex);
if (!file->private_data) {
ret = -EINVAL;
} else {
ret = free_layer(layer->layer_id);
if (!ret)
file->private_data = NULL;
}
mutex_unlock(&video_layer_mutex);
break;
default:
return -EINVAL;
}
return ret;
}
#ifdef CONFIG_COMPAT
static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg)
{
long ret = 0;
switch (cmd) {
case AMSTREAM_IOC_SET_HDR_INFO:
case AMSTREAM_IOC_SET_OMX_VPTS:
case AMSTREAM_IOC_GET_OMX_VPTS:
case AMSTREAM_IOC_GET_OMX_VERSION:
case AMSTREAM_IOC_GET_OMX_INFO:
case AMSTREAM_IOC_TRICK_STAT:
case AMSTREAM_IOC_GET_TRICK_VPTS:
case AMSTREAM_IOC_GET_SYNC_ADISCON:
case AMSTREAM_IOC_GET_SYNC_VDISCON:
case AMSTREAM_IOC_GET_SYNC_ADISCON_DIFF:
case AMSTREAM_IOC_GET_SYNC_VDISCON_DIFF:
case AMSTREAM_IOC_VF_STATUS:
case AMSTREAM_IOC_GET_VIDEO_DISABLE:
case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT:
case AMSTREAM_IOC_GET_VIDEO_AXIS:
case AMSTREAM_IOC_SET_VIDEO_AXIS:
case AMSTREAM_IOC_GET_VIDEO_CROP:
case AMSTREAM_IOC_SET_VIDEO_CROP:
case AMSTREAM_IOC_GET_SCREEN_MODE:
case AMSTREAM_IOC_SET_SCREEN_MODE:
case AMSTREAM_IOC_GET_BLACKOUT_POLICY:
case AMSTREAM_IOC_SET_BLACKOUT_POLICY:
case AMSTREAM_IOC_GET_FREERUN_MODE:
case AMSTREAM_IOC_GET_3D_TYPE:
case AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE:
case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR:
case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT:
case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON:
case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT:
case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE:
case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE:
case AMSTREAM_IOC_GET_VIDEOPIP_AXIS:
case AMSTREAM_IOC_SET_VIDEOPIP_AXIS:
case AMSTREAM_IOC_GET_VIDEOPIP_CROP:
case AMSTREAM_IOC_SET_VIDEOPIP_CROP:
case AMSTREAM_IOC_GET_PIP_SCREEN_MODE:
case AMSTREAM_IOC_SET_PIP_SCREEN_MODE:
case AMSTREAM_IOC_GET_PIP_ZORDER:
case AMSTREAM_IOC_SET_PIP_ZORDER:
case AMSTREAM_IOC_GET_ZORDER:
case AMSTREAM_IOC_SET_ZORDER:
case AMSTREAM_IOC_QUERY_LAYER:
case AMSTREAM_IOC_ALLOC_LAYER:
case AMSTREAM_IOC_FREE_LAYER:
arg = (unsigned long) compat_ptr(arg);
case AMSTREAM_IOC_TRICKMODE:
case AMSTREAM_IOC_VPAUSE:
case AMSTREAM_IOC_AVTHRESH:
case AMSTREAM_IOC_SYNCTHRESH:
case AMSTREAM_IOC_SYNCENABLE:
case AMSTREAM_IOC_SET_SYNC_ADISCON:
case AMSTREAM_IOC_SET_SYNC_VDISCON:
case AMSTREAM_IOC_SET_SYNC_ADISCON_DIFF:
case AMSTREAM_IOC_SET_SYNC_VDISCON_DIFF:
case AMSTREAM_IOC_SET_VIDEO_DISABLE:
case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT:
case AMSTREAM_IOC_CLEAR_VBUF:
case AMSTREAM_IOC_CLEAR_VIDEO:
case AMSTREAM_IOC_CLEAR_PIP_VBUF:
case AMSTREAM_IOC_CLEAR_VIDEOPIP:
case AMSTREAM_IOC_SET_FREERUN_MODE:
case AMSTREAM_IOC_DISABLE_SLOW_SYNC:
case AMSTREAM_IOC_SET_3D_TYPE:
case AMSTREAM_IOC_SET_VSYNC_UPINT:
case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR:
case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT:
case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED:
case AMSTREAM_IOC_SET_VIDEOPEEK:
return amvideo_ioctl(file, cmd, arg);
default:
return -EINVAL;
}
return ret;
}
#endif
static unsigned int amvideo_poll(struct file *file, poll_table *wait_table)
{
poll_wait(file, &amvideo_trick_wait, wait_table);
if (atomic_read(&trickmode_framedone)) {
atomic_set(&trickmode_framedone, 0);
return POLLOUT | POLLWRNORM;
}
return 0;
}
static unsigned int amvideo_poll_poll(struct file *file, poll_table *wait_table)
{
poll_wait(file, &amvideo_event_wait, wait_table);
if (atomic_read(&video_sizechange)) {
atomic_set(&video_sizechange, 0);
return POLLIN | POLLWRNORM;
}
if (frame_render_ready == 1) {
frame_render_ready = 2;
return POLLIN | POLLWRNORM;
}
return 0;
}
static const struct file_operations amvideo_fops = {
.owner = THIS_MODULE,
.open = amvideo_open,
.release = amvideo_release,
.unlocked_ioctl = amvideo_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = amvideo_compat_ioctl,
#endif
.poll = amvideo_poll,
};
static const struct file_operations amvideo_poll_fops = {
.owner = THIS_MODULE,
.open = amvideo_poll_open,
.release = amvideo_poll_release,
.poll = amvideo_poll_poll,
};
/*********************************************************
* SYSFS property functions
*********************************************************/
#define MAX_NUMBER_PARA 10
#define AMVIDEO_CLASS_NAME "video"
#define AMVIDEO_POLL_CLASS_NAME "video_poll"
static int parse_para(const char *para, int para_num, int *result)
{
char *token = NULL;
char *params, *params_base;
int *out = result;
int len = 0, count = 0;
int res = 0;
int ret = 0;
if (!para)
return 0;
params = kstrdup(para, GFP_KERNEL);
params_base = params;
token = params;
if (token) {
len = strlen(token);
do {
token = strsep(&params, " ");
if (!token)
break;
while (token && (isspace(*token)
|| !isgraph(*token)) && len) {
token++;
len--;
}
if (len == 0)
break;
ret = kstrtoint(token, 0, &res);
if (ret < 0)
break;
len = strlen(token);
*out++ = res;
count++;
} while ((count < para_num) && (len > 0));
}
kfree(params_base);
return count;
}
static void set_video_crop(
struct disp_info_s *layer, const char *para)
{
int parsed[4];
if (likely(parse_para(para, 4, parsed) == 4))
_set_video_crop(layer, parsed);
amlog_mask(LOG_MASK_SYSFS,
"video crop=>x0:%d,y0:%d,x1:%d,y1:%d\n ",
parsed[0], parsed[1], parsed[2], parsed[3]);
}
static void set_video_speed_check(const char *para)
{
int parsed[2];
struct disp_info_s *layer = &glayer_info[0];
if (likely(parse_para(para, 2, parsed) == 2)) {
layer->speed_check_height = parsed[0];
layer->speed_check_width = parsed[1];
}
amlog_mask(LOG_MASK_SYSFS,
"video speed_check=>h:%d,w:%d\n ", parsed[0], parsed[1]);
}
static void set_video_window(
struct disp_info_s *layer, const char *para)
{
int parsed[4];
if (likely(parse_para(para, 4, parsed) == 4))
_set_video_window(layer, parsed);
amlog_mask(LOG_MASK_SYSFS,
"video=>x0:%d,y0:%d,x1:%d,y1:%d\n ",
parsed[0], parsed[1], parsed[2], parsed[3]);
}
static ssize_t 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;
video_property_changed = 1;
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;
video_property_changed = 1;
}
}
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_state_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
ssize_t len = 0;
struct vppfilter_mode_s *vpp_filter = NULL;
if (!cur_frame_par)
return len;
vpp_filter = &cur_frame_par->vpp_filter;
len += sprintf(buf + len,
"zoom_start_x_lines:%u.zoom_end_x_lines:%u.\n",
zoom_start_x_lines, zoom_end_x_lines);
len += sprintf(buf + len,
"zoom_start_y_lines:%u.zoom_end_y_lines:%u.\n",
zoom_start_y_lines, zoom_end_y_lines);
len += sprintf(buf + len, "frame parameters: pic_in_height %u.\n",
cur_frame_par->VPP_pic_in_height_);
len += sprintf(buf + len,
"frame parameters: VPP_line_in_length_ %u.\n",
cur_frame_par->VPP_line_in_length_);
len += sprintf(buf + len, "vscale_skip_count %u.\n",
cur_frame_par->vscale_skip_count);
len += sprintf(buf + len, "hscale_skip_count %u.\n",
cur_frame_par->hscale_skip_count);
len += sprintf(buf + len, "supscl_path %u.\n",
cur_frame_par->supscl_path);
len += sprintf(buf + len, "supsc0_enable %u.\n",
cur_frame_par->supsc0_enable);
len += sprintf(buf + len, "supsc1_enable %u.\n",
cur_frame_par->supsc1_enable);
len += sprintf(buf + len, "supsc0_hori_ratio %u.\n",
cur_frame_par->supsc0_hori_ratio);
len += sprintf(buf + len, "supsc1_hori_ratio %u.\n",
cur_frame_par->supsc1_hori_ratio);
len += sprintf(buf + len, "supsc0_vert_ratio %u.\n",
cur_frame_par->supsc0_vert_ratio);
len += sprintf(buf + len, "supsc1_vert_ratio %u.\n",
cur_frame_par->supsc1_vert_ratio);
len += sprintf(buf + len, "spsc0_h_in %u.\n",
cur_frame_par->spsc0_h_in);
len += sprintf(buf + len, "spsc1_h_in %u.\n",
cur_frame_par->spsc1_h_in);
len += sprintf(buf + len, "spsc0_w_in %u.\n",
cur_frame_par->spsc0_w_in);
len += sprintf(buf + len, "spsc1_w_in %u.\n",
cur_frame_par->spsc1_w_in);
len += sprintf(buf + len, "video_input_w %u.\n",
cur_frame_par->video_input_w);
len += sprintf(buf + len, "video_input_h %u.\n",
cur_frame_par->video_input_h);
len += sprintf(buf + len, "clk_in_pps %u.\n",
cur_frame_par->clk_in_pps);
#ifdef TV_3D_FUNCTION_OPEN
len += sprintf(buf + len, "vpp_2pic_mode %u.\n",
cur_frame_par->vpp_2pic_mode);
len += sprintf(buf + len, "vpp_3d_scale %u.\n",
cur_frame_par->vpp_3d_scale);
len += sprintf(buf + len,
"vpp_3d_mode %u.\n", cur_frame_par->vpp_3d_mode);
#endif
len +=
sprintf(buf + len, "hscale phase step 0x%x.\n",
vpp_filter->vpp_hsc_start_phase_step);
len +=
sprintf(buf + len, "vscale phase step 0x%x.\n",
vpp_filter->vpp_vsc_start_phase_step);
len +=
sprintf(buf + len, "pps pre hsc enable %d.\n",
vpp_filter->vpp_pre_hsc_en);
len +=
sprintf(buf + len, "pps pre vsc enable %d.\n",
vpp_filter->vpp_pre_vsc_en);
len +=
sprintf(buf + len, "hscale filter coef %d.\n",
vpp_filter->vpp_horz_filter);
len +=
sprintf(buf + len, "vscale filter coef %d.\n",
vpp_filter->vpp_vert_filter);
len +=
sprintf(buf + len, "vpp_vert_chroma_filter_en %d.\n",
vpp_filter->vpp_vert_chroma_filter_en);
len +=
sprintf(buf + len, "post_blend_vd_h_start 0x%x.\n",
cur_frame_par->VPP_post_blend_vd_h_start_);
len +=
sprintf(buf + len, "post_blend_vd_h_end 0x%x.\n",
cur_frame_par->VPP_post_blend_vd_h_end_);
len +=
sprintf(buf + len, "post_blend_vd_v_start 0x%x.\n",
cur_frame_par->VPP_post_blend_vd_v_start_);
len +=
sprintf(buf + len, "post_blend_vd_v_end 0x%x.\n",
cur_frame_par->VPP_post_blend_vd_v_end_);
len +=
sprintf(buf + len, "VPP_hd_start_lines_ 0x%x.\n",
cur_frame_par->VPP_hd_start_lines_);
len +=
sprintf(buf + len, "VPP_hd_end_lines_ 0x%x.\n",
cur_frame_par->VPP_hd_end_lines_);
len +=
sprintf(buf + len, "VPP_vd_start_lines_ 0x%x.\n",
cur_frame_par->VPP_vd_start_lines_);
len +=
sprintf(buf + len, "VPP_vd_end_lines_ 0x%x.\n",
cur_frame_par->VPP_vd_end_lines_);
len +=
sprintf(buf + len, "VPP_hsc_startp 0x%x.\n",
cur_frame_par->VPP_hsc_startp);
len +=
sprintf(buf + len, "VPP_hsc_endp 0x%x.\n",
cur_frame_par->VPP_hsc_endp);
len +=
sprintf(buf + len, "VPP_vsc_startp 0x%x.\n",
cur_frame_par->VPP_vsc_startp);
len +=
sprintf(buf + len, "VPP_vsc_endp 0x%x.\n",
cur_frame_par->VPP_vsc_endp);
return len;
}
static ssize_t 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];
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (video_scaler_mode) {
x = content_left;
y = content_top;
w = content_w;
h = content_h;
} else
#endif
{
x = layer->layer_left;
y = layer->layer_top;
w = layer->layer_width;
h = layer->layer_height;
}
return snprintf(buf, 40, "%d %d %d %d\n", x, y, x + w - 1, y + h - 1);
}
static ssize_t 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];
video_property_changed = 1;
amlog_mask(LOG_MASK_SYSFS,
"video_offset=>x0:%d,y0:%d\n ",
parsed[0], parsed[1]);
}
mutex_unlock(&video_module_mutex);
return count;
}
static ssize_t 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;
video_property_changed = 1;
}
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",
"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 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;
video_property_changed = 1;
}
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 = kstrtoint(buf, 0, &blackout);
if (r < 0)
return -EINVAL;
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("%s(%d)\n", __func__, blackout);
return count;
}
static ssize_t video_seek_flag_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", video_seek_flag);
}
static ssize_t video_seek_flag_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtoint(buf, 0, &video_seek_flag);
if (r < 0)
return -EINVAL;
return count;
}
#ifdef PTS_TRACE_DEBUG
static ssize_t pts_trace_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d %d %d %d %d %d %d %d\n"
"%d %d %d %d %d %d %d %d\n"
"%0x %0x %0x %0x %0x %0x %0x %0x\n"
"%0x %0x %0x %0x %0x %0x %0x %0x\n"
"%0x %0x %0x %0x %0x %0x %0x %0x\n"
"%0x %0x %0x %0x %0x %0x %0x %0x\n",
pts_trace_his[0], pts_trace_his[1], pts_trace_his[2],
pts_trace_his[3], pts_trace_his[4], pts_trace_his[5],
pts_trace_his[6], pts_trace_his[7], pts_trace_his[8],
pts_trace_his[9], pts_trace_his[10], pts_trace_his[11],
pts_trace_his[12], pts_trace_his[13], pts_trace_his[14],
pts_trace_his[15],
pts_his[0], pts_his[1], pts_his[2], pts_his[3],
pts_his[4], pts_his[5], pts_his[6], pts_his[7],
pts_his[8], pts_his[9], pts_his[10], pts_his[11],
pts_his[12], pts_his[13], pts_his[14], pts_his[15],
scr_his[0], scr_his[1], scr_his[2], scr_his[3],
scr_his[4], scr_his[5], scr_his[6], scr_his[7],
scr_his[8], scr_his[9], scr_his[10], scr_his[11],
scr_his[12], scr_his[13], scr_his[14], scr_his[15]);
}
#endif
static ssize_t 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)
WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y +
cur_dev->vpp_off, val, 8, 9);
else
WRITE_VCBUS_REG_BITS(VPP_VADJ1_Y +
cur_dev->vpp_off, val << 1, 8, 10);
WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ1_EN);
return count;
}
static ssize_t 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)
WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y +
cur_dev->vpp_off, val, 8, 9);
else
WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y +
cur_dev->vpp_off, val << 1, 8, 10);
WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ2_EN);
return count;
}
static ssize_t vpp_contrast_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n",
(int)(READ_VCBUS_REG(VPP_VADJ2_Y + cur_dev->vpp_off) &
0xff) - 0x80);
}
static ssize_t vpp_contrast_store(struct class *cla,
struct class_attribute *attr, const char *buf,
size_t count)
{
int r;
int val;
r = kstrtoint(buf, 0, &val);
if ((r < 0) || (val < -127) || (val > 127))
return -EINVAL;
val += 0x80;
WRITE_VCBUS_REG_BITS(VPP_VADJ2_Y + cur_dev->vpp_off, val, 0, 8);
WRITE_VCBUS_REG(VPP_VADJ_CTRL + cur_dev->vpp_off, VPP_VADJ2_EN);
return count;
}
static ssize_t 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);
}
static ssize_t video_rgb_screen_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "0x%x\n", rgb_screen);
}
#define SCALE 6
static short R_Cr[] = { -11484, -11394, -11305, -11215, -11125,
-11036, -10946, -10856, -10766, -10677, -10587, -10497, -10407,
-10318, -10228, -10138, -10049, -9959, -9869, -9779, -9690, -9600,
-9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882, -8792, -8703,
-8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985, -7895, -7805,
-7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088, -6998, -6908,
-6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190, -6101, -6011,
-5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293, -5203, -5113,
-5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396, -4306, -4216,
-4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498, -3409, -3319,
-3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601, -2511, -2422,
-2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704, -1614, -1524,
-1435, -1345, -1255, -1165, -1076, -986, -896, -807, -717, -627, -537,
-448, -358, -268, -178, -89, 0, 90, 179, 269, 359, 449, 538, 628, 718,
808, 897, 987, 1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795,
1884, 1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782,
2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679, 3769,
3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576, 4666, 4756,
4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473, 5563, 5653, 5743,
5832, 5922, 6012, 6102, 6191, 6281, 6371, 6460, 6550, 6640, 6730,
6819, 6909, 6999, 7089, 7178, 7268, 7358, 7447, 7537, 7627, 7717,
7806, 7896, 7986, 8076, 8165, 8255, 8345, 8434, 8524, 8614, 8704,
8793, 8883, 8973, 9063, 9152, 9242, 9332, 9421, 9511, 9601, 9691,
9780, 9870, 9960, 10050, 10139, 10229, 10319, 10408, 10498, 10588,
10678, 10767, 10857, 10947, 11037, 11126, 11216, 11306, 11395 };
static short G_Cb[] = { 2819, 2797, 2775, 2753, 2731, 2709, 2687,
2665, 2643, 2621, 2599, 2577, 2555, 2533, 2511, 2489, 2467, 2445,
2423, 2401, 2379, 2357, 2335, 2313, 2291, 2269, 2247, 2225, 2202,
2180, 2158, 2136, 2114, 2092, 2070, 2048, 2026, 2004, 1982, 1960,
1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784, 1762, 1740, 1718,
1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520, 1498, 1476,
1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255, 1233,
1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991, 969,
947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727, 705, 683, 661,
639, 617, 595, 573, 551, 529, 507, 485, 463, 440, 418, 396, 374, 352,
330, 308, 286, 264, 242, 220, 198, 176, 154, 132, 110, 88, 66, 44, 22,
0, -21, -43, -65, -87, -109, -131, -153, -175, -197, -219, -241, -263,
-285, -307, -329, -351, -373, -395, -417, -439, -462, -484, -506,
-528, -550, -572, -594, -616, -638, -660, -682, -704, -726, -748,
-770, -792, -814, -836, -858, -880, -902, -924, -946, -968, -990,
-1012, -1034, -1056, -1078, -1100, -1122, -1144, -1166, -1188, -1210,
-1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387, -1409, -1431,
-1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651,
-1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871,
-1893, -1915, -1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091,
-2113, -2135, -2157, -2179, -2201, -2224, -2246, -2268, -2290, -2312,
-2334, -2356, -2378, -2400, -2422, -2444, -2466, -2488, -2510, -2532,
-2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708, -2730, -2752,
-2774, -2796 };
static short G_Cr[] = { 5850, 5805, 5759, 5713, 5667, 5622, 5576,
5530, 5485, 5439, 5393, 5347, 5302, 5256, 5210, 5165, 5119, 5073,
5028, 4982, 4936, 4890, 4845, 4799, 4753, 4708, 4662, 4616, 4570,
4525, 4479, 4433, 4388, 4342, 4296, 4251, 4205, 4159, 4113, 4068,
4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702, 3656, 3611, 3565,
3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154, 3108, 3062,
3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605, 2559,
2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057,
2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554,
1508, 1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051,
1006, 960, 914, 868, 823, 777, 731, 686, 640, 594, 548, 503, 457, 411,
366, 320, 274, 229, 183, 137, 91, 46, 0, -45, -90, -136, -182, -228,
-273, -319, -365, -410, -456, -502, -547, -593, -639, -685, -730,
-776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187,
-1233, -1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644,
-1690, -1736, -1781, -1827, -1873, -1919, -1964, -2010, -2056, -2101,
-2147, -2193, -2239, -2284, -2330, -2376, -2421, -2467, -2513, -2558,
-2604, -2650, -2696, -2741, -2787, -2833, -2878, -2924, -2970, -3016,
-3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427, -3473,
-3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930,
-3975, -4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387,
-4432, -4478, -4524, -4569, -4615, -4661, -4707, -4752, -4798, -4844,
-4889, -4935, -4981, -5027, -5072, -5118, -5164, -5209, -5255, -5301,
-5346, -5392, -5438, -5484, -5529, -5575, -5621, -5666, -5712, -5758,
-5804 };
static short B_Cb[] = { -14515, -14402, -14288, -14175, -14062,
-13948, -13835, -13721, -13608, -13495, -13381, -13268, -13154,
-13041, -12928, -12814, -12701, -12587, -12474, -12360, -12247,
-12134, -12020, -11907, -11793, -11680, -11567, -11453, -11340,
-11226, -11113, -11000, -10886, -10773, -10659, -10546, -10433,
-10319, -10206, -10092, -9979, -9865, -9752, -9639, -9525, -9412,
-9298, -9185, -9072, -8958, -8845, -8731, -8618, -8505, -8391, -8278,
-8164, -8051, -7938, -7824, -7711, -7597, -7484, -7371, -7257, -7144,
-7030, -6917, -6803, -6690, -6577, -6463, -6350, -6236, -6123, -6010,
-5896, -5783, -5669, -5556, -5443, -5329, -5216, -5102, -4989, -4876,
-4762, -4649, -4535, -4422, -4309, -4195, -4082, -3968, -3855, -3741,
-3628, -3515, -3401, -3288, -3174, -3061, -2948, -2834, -2721, -2607,
-2494, -2381, -2267, -2154, -2040, -1927, -1814, -1700, -1587, -1473,
-1360, -1246, -1133, -1020, -906, -793, -679, -566, -453, -339, -226,
-112, 0, 113, 227, 340, 454, 567, 680, 794, 907, 1021, 1134, 1247,
1361, 1474, 1588, 1701, 1815, 1928, 2041, 2155, 2268, 2382, 2495,
2608, 2722, 2835, 2949, 3062, 3175, 3289, 3402, 3516, 3629, 3742,
3856, 3969, 4083, 4196, 4310, 4423, 4536, 4650, 4763, 4877, 4990,
5103, 5217, 5330, 5444, 5557, 5670, 5784, 5897, 6011, 6124, 6237,
6351, 6464, 6578, 6691, 6804, 6918, 7031, 7145, 7258, 7372, 7485,
7598, 7712, 7825, 7939, 8052, 8165, 8279, 8392, 8506, 8619, 8732,
8846, 8959, 9073, 9186, 9299, 9413, 9526, 9640, 9753, 9866, 9980,
10093, 10207, 10320, 10434, 10547, 10660, 10774, 10887, 11001, 11114,
11227, 11341, 11454, 11568, 11681, 11794, 11908, 12021, 12135, 12248,
12361, 12475, 12588, 12702, 12815, 12929, 13042, 13155, 13269, 13382,
13496, 13609, 13722, 13836, 13949, 14063, 14176, 14289, 14403
};
static u32 yuv2rgb(u32 yuv)
{
int y = (yuv >> 16) & 0xff;
int cb = (yuv >> 8) & 0xff;
int cr = yuv & 0xff;
int r, g, b;
r = y + ((R_Cr[cr]) >> SCALE);
g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE);
b = y + ((B_Cb[cb]) >> SCALE);
r = r - 16;
if (r < 0)
r = 0;
r = r*1164/1000;
g = g - 16;
if (g < 0)
g = 0;
g = g*1164/1000;
b = b - 16;
if (b < 0)
b = 0;
b = b*1164/1000;
r = (r <= 0) ? 0 : (r >= 255) ? 255 : r;
g = (g <= 0) ? 0 : (g >= 255) ? 255 : g;
b = (b <= 0) ? 0 : (b >= 255) ? 255 : b;
return (r << 16) | (g << 8) | b;
}
/* 8bit convert to 10bit */
static u32 eight2ten(u32 yuv)
{
int y = (yuv >> 16) & 0xff;
int cb = (yuv >> 8) & 0xff;
int cr = yuv & 0xff;
u32 data32;
/* txlx need check vd1 path bit width by s2u registers */
if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX) {
data32 = READ_VCBUS_REG(0x1d94) & 0xffff;
if ((data32 == 0x2000) ||
(data32 == 0x800))
return ((y << 20)<<2) | ((cb << 10)<<2) | (cr<<2);
else
return (y << 20) | (cb << 10) | cr;
} else
return (y << 20) | (cb << 10) | cr;
}
static u32 rgb2yuv(u32 rgb)
{
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
int y, u, v;
y = ((47*r + 157*g + 16*b + 128) >> 8) + 16;
u = ((-26*r - 87*g + 112*b + 128) >> 8) + 128;
v = ((112*r - 102*g - 10*b + 128) >> 8) + 128;
return (y << 16) | (u << 8) | v;
}
static ssize_t video_test_screen_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
unsigned int data = 0x0;
r = kstrtoint(buf, 0, &test_screen);
if (r < 0)
return -EINVAL;
#if 0/*no use now*/
/* vdin0 pre post blend enable or disabled */
data = READ_VCBUS_REG(VPP_MISC);
if (test_screen & 0x01000000)
data |= VPP_VD1_PREBLEND;
else
data &= (~VPP_VD1_PREBLEND);
if (test_screen & 0x02000000)
data |= VPP_VD1_POSTBLEND;
else
data &= (~VPP_VD1_POSTBLEND);
#endif
#if DEBUG_TMP
if (test_screen & 0x04000000)
data |= VPP_VD2_PREBLEND;
else
data &= (~VPP_VD2_PREBLEND);
if (test_screen & 0x08000000)
data |= VPP_VD2_POSTBLEND;
else
data &= (~VPP_VD2_POSTBLEND);
#endif
/* show test screen YUV blend*/
if (!legacy_vpp)
WRITE_VCBUS_REG(
VPP_POST_BLEND_BLEND_DUMMY_DATA,
test_screen & 0x00ffffff);
else if (is_meson_gxm_cpu() ||
(get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX))
/* bit width change to 10bit in gxm, 10/12 in txlx*/
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
eight2ten(test_screen & 0x00ffffff));
else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB)
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
yuv2rgb(test_screen & 0x00ffffff));
else if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB)
if (READ_VCBUS_REG(VIU_OSD1_BLK0_CFG_W0) & 0x80)
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
test_screen & 0x00ffffff);
else /* RGB blend */
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
yuv2rgb(test_screen & 0x00ffffff));
else
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
test_screen & 0x00ffffff);
#if 0/*no use*/
WRITE_VCBUS_REG(VPP_MISC, data);
#endif
if (debug_flag & DEBUG_FLAG_BLACKOUT) {
pr_info("%s write(VPP_MISC,%x) write(VPP_DUMMY_DATA1, %x)\n",
__func__, data, test_screen & 0x00ffffff);
}
return count;
}
static ssize_t 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 = kstrtoint(buf, 0, &rgb_screen);
if (r < 0)
return -EINVAL;
#if DEBUG_TMP
/* vdin0 pre post blend enable or disabled */
data = READ_VCBUS_REG(VPP_MISC);
if (rgb_screen & 0x01000000)
data |= VPP_VD1_PREBLEND;
else
data &= (~VPP_VD1_PREBLEND);
if (rgb_screen & 0x02000000)
data |= VPP_VD1_POSTBLEND;
else
data &= (~VPP_VD1_POSTBLEND);
if (test_screen & 0x04000000)
data |= VPP_VD2_PREBLEND;
else
data &= (~VPP_VD2_PREBLEND);
if (test_screen & 0x08000000)
data |= VPP_VD2_POSTBLEND;
else
data &= (~VPP_VD2_POSTBLEND);
#endif
/* show test screen YUV blend*/
yuv_eight = rgb2yuv(rgb_screen & 0x00ffffff);
if (!legacy_vpp) {
WRITE_VCBUS_REG(
VPP_POST_BLEND_BLEND_DUMMY_DATA,
yuv_eight & 0x00ffffff);
} else if (is_meson_gxtvbb_cpu()) {
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
rgb_screen & 0x00ffffff);
} else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {
WRITE_VCBUS_REG(VPP_DUMMY_DATA1,
eight2ten(yuv_eight & 0x00ffffff));
}
/* WRITE_VCBUS_REG(VPP_MISC, data); */
if (debug_flag & DEBUG_FLAG_BLACKOUT) {
pr_info("%s write(VPP_DUMMY_DATA1, %x)\n",
__func__, rgb_screen & 0x00ffffff);
}
return count;
}
static ssize_t 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 = kstrtoint(buf, 0, &factor);
if (r < 0)
return -EINVAL;
if (vpp_set_nonlinear_factor(layer, factor) == 0)
video_property_changed = 1;
return count;
}
static ssize_t video_disable_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", 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_BLACKOUT)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (_video_set_disable(val) < 0)
return -EINVAL;
return count;
}
static ssize_t video_global_output_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", video_global_output);
}
static ssize_t video_global_output_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtoint(buf, 0, &video_global_output);
if (r < 0)
return -EINVAL;
pr_info("%s(%d)\n", __func__, video_global_output);
return count;
}
static ssize_t 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;
cur_width = 0;
cur_height = 0;
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &hold_video);
if (r < 0)
return -EINVAL;
return count;
}
static ssize_t 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 = kstrtoint(buf, 0, &freerun_mode);
if (r < 0)
return -EINVAL;
if (debug_flag)
pr_info("%s(%d)\n", __func__, freerun_mode);
return count;
}
static ssize_t video_speed_check_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)
{
#ifdef TV_3D_FUNCTION_OPEN
u32 type;
int r;
r = kstrtoint(buf, 0, &type);
if (r < 0)
return -EINVAL;
if (type != process_3d_type) {
process_3d_type = type;
if (mvc_flag)
process_3d_type |= MODE_3D_MVC;
video_property_changed = 1;
if ((process_3d_type & MODE_3D_FA)
&& cur_dispbuf && !cur_dispbuf->trans_fmt)
/*notify di 3d mode is frame alternative mode,1*/
/*passing two buffer in one frame */
vf_notify_receiver_by_name("deinterlace",
VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE,
(void *)1);
else
vf_notify_receiver_by_name("deinterlace",
VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE,
(void *)0);
}
#endif
return len;
}
static ssize_t threedim_mode_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
#ifdef TV_3D_FUNCTION_OPEN
return sprintf(buf, "process type 0x%x,trans fmt %u.\n",
process_3d_type, video_3d_format);
#else
return 0;
#endif
}
static ssize_t frame_addr_show(struct class *cla, struct class_attribute *attr,
char *buf)
{
struct canvas_s canvas;
u32 addr[3];
if (cur_dispbuf) {
canvas_read(cur_dispbuf->canvas0Addr & 0xff, &canvas);
addr[0] = canvas.addr;
canvas_read((cur_dispbuf->canvas0Addr >> 8) & 0xff, &canvas);
addr[1] = canvas.addr;
canvas_read((cur_dispbuf->canvas0Addr >> 16) & 0xff, &canvas);
addr[2] = canvas.addr;
return sprintf(buf, "0x%x-0x%x-0x%x\n", addr[0], addr[1],
addr[2]);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_canvas_width_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
struct canvas_s canvas;
u32 width[3];
if (cur_dispbuf) {
canvas_read(cur_dispbuf->canvas0Addr & 0xff, &canvas);
width[0] = canvas.width;
canvas_read((cur_dispbuf->canvas0Addr >> 8) & 0xff, &canvas);
width[1] = canvas.width;
canvas_read((cur_dispbuf->canvas0Addr >> 16) & 0xff, &canvas);
width[2] = canvas.width;
return sprintf(buf, "%d-%d-%d\n",
width[0], width[1], width[2]);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_canvas_height_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
struct canvas_s canvas;
u32 height[3];
if (cur_dispbuf) {
canvas_read(cur_dispbuf->canvas0Addr & 0xff, &canvas);
height[0] = canvas.height;
canvas_read((cur_dispbuf->canvas0Addr >> 8) & 0xff, &canvas);
height[1] = canvas.height;
canvas_read((cur_dispbuf->canvas0Addr >> 16) & 0xff, &canvas);
height[2] = canvas.height;
return sprintf(buf, "%d-%d-%d\n", height[0], height[1],
height[2]);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_width_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
if (hold_video == 1)
return sprintf(buf, "%d\n", cur_width);
if (cur_dispbuf) {
if (cur_dispbuf->type & VIDTYPE_COMPRESS)
return sprintf(buf, "%d\n", cur_dispbuf->compWidth);
else
return sprintf(buf, "%d\n", cur_dispbuf->width);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_height_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
if (hold_video == 1)
return sprintf(buf, "%d\n", cur_height);
if (cur_dispbuf) {
if (cur_dispbuf->type & VIDTYPE_COMPRESS)
return sprintf(buf, "%d\n", cur_dispbuf->compHeight);
else
return sprintf(buf, "%d\n", cur_dispbuf->height);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_org_width_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
if ((cur_dispbuf) && (cur_dispbuf->org_width))
return sprintf(buf, "%d\n", cur_dispbuf->org_width);
else
return frame_width_show(cla, attr, buf);
}
static ssize_t frame_org_height_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
if ((cur_dispbuf) && (cur_dispbuf->org_height))
return sprintf(buf, "%d\n", cur_dispbuf->org_height);
else
return frame_height_show(cla, attr, buf);
}
static ssize_t frame_render_ready_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", frame_render_ready ? 1 : 0);
}
static ssize_t frame_format_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
ssize_t ret = 0;
if (cur_dispbuf) {
if ((cur_dispbuf->type & VIDTYPE_TYPEMASK) ==
VIDTYPE_INTERLACE_TOP)
ret = sprintf(buf, "interlace-top\n");
else if ((cur_dispbuf->type & VIDTYPE_TYPEMASK) ==
VIDTYPE_INTERLACE_BOTTOM)
ret = sprintf(buf, "interlace-bottom\n");
else
ret = sprintf(buf, "progressive\n");
if (cur_dispbuf->type & VIDTYPE_COMPRESS)
ret += sprintf(buf + ret, "Compressed\n");
return ret;
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_aspect_ratio_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
if (cur_dispbuf) {
u32 ar = (cur_dispbuf->ratio_control &
DISP_RATIO_ASPECT_RATIO_MASK) >>
DISP_RATIO_ASPECT_RATIO_BIT;
if (ar)
return sprintf(buf, "0x%x\n", ar);
else
return sprintf(buf, "0x%x\n",
(cur_dispbuf->width << 8) /
cur_dispbuf->height);
}
return sprintf(buf, "NA\n");
}
static ssize_t frame_rate_show(struct class *cla, struct class_attribute *attr,
char *buf)
{
u32 cnt = frame_count - last_frame_count;
u32 time = jiffies;
u32 tmp = time;
u32 rate = 0;
u32 vsync_rate;
ssize_t ret = 0;
time -= last_frame_time;
last_frame_time = tmp;
last_frame_count = frame_count;
if (time == 0)
return 0;
rate = 100 * cnt * HZ / time;
vsync_rate = 100 * vsync_count * HZ / time;
if (vinfo->sync_duration_den > 0) {
ret =
sprintf(buf,
"VF.fps=%d.%02d panel fps %d, dur/is: %d,v/s=%d.%02d,inc=%d\n",
rate / 100, rate % 100,
vinfo->sync_duration_num /
vinfo->sync_duration_den,
time, vsync_rate / 100, vsync_rate % 100,
vsync_pts_inc);
}
if ((debugflags & DEBUG_FLAG_CALC_PTS_INC) && time > HZ * 10
&& vsync_rate > 0) {
if ((vsync_rate * vsync_pts_inc / 100) != 90000)
vsync_pts_inc = 90000 * 100 / (vsync_rate);
}
vsync_count = 0;
return ret;
}
static ssize_t vframe_states_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
int ret = 0;
struct vframe_states states;
unsigned long flags;
struct vframe_s *vf;
if (video_vf_get_states(&states) == 0) {
ret += sprintf(buf + ret, "vframe_pool_size=%d\n",
states.vf_pool_size);
ret += sprintf(buf + ret, "vframe buf_free_num=%d\n",
states.buf_free_num);
ret += sprintf(buf + ret, "vframe buf_recycle_num=%d\n",
states.buf_recycle_num);
ret += sprintf(buf + ret, "vframe buf_avail_num=%d\n",
states.buf_avail_num);
spin_lock_irqsave(&lock, flags);
vf = video_vf_peek();
if (vf) {
ret += sprintf(buf + ret,
"vframe ready frame delayed =%dms\n",
(int)(jiffies_64 -
vf->ready_jiffies64) * 1000 /
HZ);
ret += sprintf(buf + ret,
"vf index=%d\n", vf->index);
ret += sprintf(buf + ret,
"vf->pts=%d\n", vf->pts);
ret += sprintf(buf + ret,
"cur vpts=%d\n",
timestamp_vpts_get());
ret += sprintf(buf + ret,
"vf type=%d\n",
vf->type);
if (vf->type & VIDTYPE_COMPRESS) {
ret += sprintf(buf + ret,
"vf compHeadAddr=%x\n",
vf->compHeadAddr);
ret += sprintf(buf + ret,
"vf compBodyAddr =%x\n",
vf->compBodyAddr);
} else {
ret += sprintf(buf + ret,
"vf canvas0Addr=%x\n",
vf->canvas0Addr);
ret += sprintf(buf + ret,
"vf canvas1Addr=%x\n",
vf->canvas1Addr);
ret += sprintf(buf + ret,
"vf canvas0Addr.y.addr=%x(%d)\n",
canvas_get_addr(
canvasY(vf->canvas0Addr)),
canvas_get_addr(
canvasY(vf->canvas0Addr)));
ret += sprintf(buf + ret,
"vf canvas0Adr.uv.adr=%x(%d)\n",
canvas_get_addr(
canvasUV(vf->canvas0Addr)),
canvas_get_addr(
canvasUV(vf->canvas0Addr)));
}
}
spin_unlock_irqrestore(&lock, flags);
} else
ret += sprintf(buf + ret, "vframe no states\n");
return ret;
}
#ifdef CONFIG_AM_VOUT
static ssize_t device_resolution_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
const struct vinfo_s *info;
if (cur_dev == &video_dev[0])
info = get_current_vinfo();
else
info = get_current_vinfo2();
#else
const struct vinfo_s *info = get_current_vinfo();
#endif
if (info != NULL)
return sprintf(buf, "%dx%d\n", info->width, info->height);
else
return sprintf(buf, "0x0\n");
}
#endif
static ssize_t 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 = kstrtoint(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 = kstrtoint(buf, 0, &vsync_pts_inc_upint);
if (r < 0)
return -EINVAL;
if (debug_flag)
pr_info("%s(%d)\n", __func__, vsync_pts_inc_upint);
return count;
}
static ssize_t slowsync_repeat_enable_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "slowsync repeate enable = %d\n",
slowsync_repeat_enable);
}
static ssize_t slowsync_repeat_enable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
r = kstrtoint(buf, 0, &slowsync_repeat_enable);
if (r < 0)
return -EINVAL;
if (debug_flag)
pr_info("%s(%d)\n", __func__, slowsync_repeat_enable);
return count;
}
static ssize_t 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 = kstrtoint(buf, 0, &vsync_slow_factor);
if (r < 0)
return -EINVAL;
if (debug_flag)
pr_info("%s(%d)\n", __func__, vsync_slow_factor);
return count;
}
static ssize_t fps_info_show(struct class *cla, struct class_attribute *attr,
char *buf)
{
u32 cnt = frame_count - last_frame_count;
u32 time = jiffies;
u32 input_fps = 0;
u32 tmp = time;
time -= last_frame_time;
last_frame_time = tmp;
last_frame_count = frame_count;
if (time != 0)
output_fps = cnt * HZ / time;
if (cur_dispbuf && cur_dispbuf->duration > 0) {
input_fps = 96000 / cur_dispbuf->duration;
if (output_fps > input_fps)
output_fps = input_fps;
} else
input_fps = output_fps;
return sprintf(buf, "input_fps:0x%x output_fps:0x%x drop_fps:0x%x\n",
input_fps, output_fps, input_fps - output_fps);
}
static ssize_t video_layer1_state_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
/*return sprintf(buf, "%d\n",*/
/*(READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off)*/
/*& VPP_VD1_PREBLEND) ? 1 : 0);*/
return sprintf(buf, "%d\n", video_enabled);
}
void set_video_angle(u32 s_value)
{
struct disp_info_s *layer = &glayer_info[0];
if ((s_value <= 3) && (layer->angle != s_value)) {
layer->angle = s_value;
pr_info("video angle:%d\n", layer->angle);
}
}
EXPORT_SYMBOL(set_video_angle);
static ssize_t 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 = kstrtoint(buf, 0, &s_value);
if (r < 0)
return -EINVAL;
set_video_angle(s_value);
return strnlen(buf, count);
}
static ssize_t show_first_frame_nosync_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", show_first_frame_nosync ? 1 : 0);
}
static ssize_t show_first_frame_nosync_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int value;
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
if (value == 0)
show_first_frame_nosync = false;
else
show_first_frame_nosync = true;
return count;
}
static ssize_t show_first_picture_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int value;
r = kstrtoint(buf, 0, &value);
if (r < 0)
return -EINVAL;
if (value == 0)
show_first_picture = false;
else
show_first_picture = true;
return count;
}
static ssize_t 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_BLACKOUT)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (val == 1)
try_free_keep_video(1);
return count;
}
static ssize_t free_cma_buffer_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int val;
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (val == 1) {
pr_info("start to free cma buffer\n");
#if DEBUG_TMP
vh265_free_cmabuf();
vh264_4k_free_cmabuf();
vdec_free_cmabuf();
#endif
}
return count;
}
static ssize_t pic_mode_info_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
int ret = 0;
if (cur_dispbuf) {
u32 adapted_mode = (cur_dispbuf->ratio_control
& DISP_RATIO_ADAPTED_PICMODE) ? 1 : 0;
u32 info_frame = (cur_dispbuf->ratio_control
& DISP_RATIO_INFOFRAME_AVAIL) ? 1 : 0;
ret += sprintf(buf + ret, "ratio_control=0x%x\n",
cur_dispbuf->ratio_control);
ret += sprintf(buf + ret, "adapted_mode=%d\n",
adapted_mode);
ret += sprintf(buf + ret, "info_frame=%d\n",
info_frame);
ret += sprintf(buf + ret,
"hs=%d, he=%d, vs=%d, ve=%d\n",
cur_dispbuf->pic_mode.hs,
cur_dispbuf->pic_mode.he,
cur_dispbuf->pic_mode.vs,
cur_dispbuf->pic_mode.ve);
ret += sprintf(buf + ret, "screen_mode=%d\n",
cur_dispbuf->pic_mode.screen_mode);
ret += sprintf(buf + ret, "custom_ar=%d\n",
cur_dispbuf->pic_mode.custom_ar);
ret += sprintf(buf + ret, "AFD_enable=%d\n",
cur_dispbuf->pic_mode.AFD_enable);
return ret;
}
return sprintf(buf, "NA\n");
}
static ssize_t video_inuse_show(struct class *class,
struct class_attribute *attr, char *buf)
{
size_t r;
mutex_lock(&video_inuse_mutex);
if (video_inuse == 0) {
r = sprintf(buf, "%d\n", video_inuse);
video_inuse = 1;
pr_info("video_inuse return 0,set 1\n");
} else {
r = sprintf(buf, "%d\n", video_inuse);
pr_info("video_inuse = %d\n", video_inuse);
}
mutex_unlock(&video_inuse_mutex);
return r;
}
static ssize_t video_inuse_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
size_t r;
int val;
mutex_lock(&video_inuse_mutex);
r = kstrtoint(buf, 0, &val);
pr_info("set video_inuse val:%d\n", val);
video_inuse = val;
mutex_unlock(&video_inuse_mutex);
if (r != 1)
return -EINVAL;
return count;
}
static ssize_t video_zorder_show(
struct class *cla,
struct class_attribute *attr,
char *buf)
{
struct disp_info_s *layer = &glayer_info[0];
return sprintf(buf, "%d\n", layer->zorder);
}
static ssize_t video_zorder_store(
struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int zorder;
int ret = 0;
struct disp_info_s *layer = &glayer_info[0];
ret = kstrtoint(buf, 0, &zorder);
if (ret < 0)
return -EINVAL;
if (zorder != layer->zorder) {
layer->zorder = zorder;
video_property_changed = 1;
}
return count;
}
static ssize_t black_threshold_show(
struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "width: %d, height: %d\n",
black_threshold_width,
black_threshold_height);
}
static ssize_t black_threshold_store(
struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int parsed[2];
if (likely(parse_para(buf, 2, parsed) == 2)) {
black_threshold_width = parsed[0];
black_threshold_height = parsed[1];
}
return strnlen(buf, count);
}
#ifdef VIDEO_PIP
int _videopip_set_disable(u32 val)
{
if (val > VIDEO_DISABLE_FORNEXT)
return -EINVAL;
disable_videopip = val;
if (disable_videopip != VIDEO_DISABLE_NONE) {
DisableVideoLayer2();
if ((disable_videopip == VIDEO_DISABLE_FORNEXT)
&& cur_pipbuf && (cur_pipbuf != &local_pip))
pip_property_changed = 1;
try_free_keep_videopip(0);
} else {
if (cur_pipbuf && (cur_pipbuf != &local_pip))
EnableVideoLayer2();
}
return 0;
}
static ssize_t 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 = kstrtoint(buf, 0, &blackout_pip);
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 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 videopip_disable_show(
struct class *cla, struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", disable_videopip);
}
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_BLACKOUT)
pr_info("%s(%s)\n", __func__, buf);
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
if (_videopip_set_disable(val) < 0)
return -EINVAL;
return count;
}
static ssize_t 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;
pip_property_changed = 1;
}
return count;
}
static ssize_t videopip_loop_show(
struct class *cla, struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", pip_loop);
}
static ssize_t videopip_loop_store(
struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int r;
int val;
r = kstrtoint(buf, 0, &val);
if (r < 0)
return -EINVAL;
pip_loop = val;
return count;
}
static ssize_t videopip_global_output_show(
struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", pip_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 = kstrtoint(buf, 0, &pip_global_output);
if (r < 0)
return -EINVAL;
pr_info("%s(%d)\n", __func__, pip_global_output);
return count;
}
static ssize_t videopip_zorder_show(
struct class *cla,
struct class_attribute *attr,
char *buf)
{
struct disp_info_s *layer = &glayer_info[1];
return sprintf(buf, "%d\n", layer->zorder);
}
static ssize_t videopip_zorder_store(
struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int zorder;
int ret = 0;
struct disp_info_s *layer = &glayer_info[1];
ret = kstrtoint(buf, 0, &zorder);
if (ret < 0)
return -EINVAL;
if (zorder != layer->zorder) {
layer->zorder = zorder;
pip_property_changed = 1;
}
return count;
}
static ssize_t videopip_state_show(
struct class *cla,
struct class_attribute *attr,
char *buf)
{
ssize_t len = 0;
struct vppfilter_mode_s *vpp_filter = NULL;
if (!curpip_frame_par)
return len;
vpp_filter = &curpip_frame_par->vpp_filter;
len += sprintf(buf + len,
"zoom2_start_x_lines:%u.zoom2_end_x_lines:%u.\n",
zoom2_start_x_lines, zoom2_end_x_lines);
len += sprintf(buf + len,
"zoom2_start_y_lines:%u.zoom2_end_y_lines:%u.\n",
zoom2_start_y_lines, zoom2_end_y_lines);
len += sprintf(buf + len, "frame parameters: pic_in_height %u.\n",
curpip_frame_par->VPP_pic_in_height_);
len += sprintf(buf + len,
"frame parameters: VPP_line_in_length_ %u.\n",
curpip_frame_par->VPP_line_in_length_);
len += sprintf(buf + len, "vscale_skip_count %u.\n",
curpip_frame_par->vscale_skip_count);
len += sprintf(buf + len, "hscale_skip_count %u.\n",
curpip_frame_par->hscale_skip_count);
len += sprintf(buf + len, "supscl_path %u.\n",
curpip_frame_par->supscl_path);
len += sprintf(buf + len, "supsc0_enable %u.\n",
curpip_frame_par->supsc0_enable);
len += sprintf(buf + len, "supsc1_enable %u.\n",
curpip_frame_par->supsc1_enable);
len += sprintf(buf + len, "supsc0_hori_ratio %u.\n",
curpip_frame_par->supsc0_hori_ratio);
len += sprintf(buf + len, "supsc1_hori_ratio %u.\n",
curpip_frame_par->supsc1_hori_ratio);
len += sprintf(buf + len, "supsc0_vert_ratio %u.\n",
curpip_frame_par->supsc0_vert_ratio);
len += sprintf(buf + len, "supsc1_vert_ratio %u.\n",
curpip_frame_par->supsc1_vert_ratio);
len += sprintf(buf + len, "spsc0_h_in %u.\n",
curpip_frame_par->spsc0_h_in);
len += sprintf(buf + len, "spsc1_h_in %u.\n",
curpip_frame_par->spsc1_h_in);
len += sprintf(buf + len, "spsc0_w_in %u.\n",
curpip_frame_par->spsc0_w_in);
len += sprintf(buf + len, "spsc1_w_in %u.\n",
curpip_frame_par->spsc1_w_in);
len += sprintf(buf + len, "video_input_w %u.\n",
curpip_frame_par->video_input_w);
len += sprintf(buf + len, "video_input_h %u.\n",
curpip_frame_par->video_input_h);
len += sprintf(buf + len, "clk_in_pps %u.\n",
curpip_frame_par->clk_in_pps);
len +=
sprintf(buf + len, "hscale phase step 0x%x.\n",
vpp_filter->vpp_hsc_start_phase_step);
len +=
sprintf(buf + len, "vscale phase step 0x%x.\n",
vpp_filter->vpp_vsc_start_phase_step);
len +=
sprintf(buf + len, "pps pre hsc enable %d.\n",
vpp_filter->vpp_pre_hsc_en);
len +=
sprintf(buf + len, "pps pre vsc enable %d.\n",
vpp_filter->vpp_pre_vsc_en);
len +=
sprintf(buf + len, "hscale filter coef %d.\n",
vpp_filter->vpp_horz_filter);
len +=
sprintf(buf + len, "vscale filter coef %d.\n",
vpp_filter->vpp_vert_filter);
len +=
sprintf(buf + len, "vpp_vert_chroma_filter_en %d.\n",
vpp_filter->vpp_vert_chroma_filter_en);
len +=
sprintf(buf + len, "post_blend_vd_h_start 0x%x.\n",
curpip_frame_par->VPP_post_blend_vd_h_start_);
len +=
sprintf(buf + len, "post_blend_vd_h_end 0x%x.\n",
curpip_frame_par->VPP_post_blend_vd_h_end_);
len +=
sprintf(buf + len, "post_blend_vd_v_start 0x%x.\n",
curpip_frame_par->VPP_post_blend_vd_v_start_);
len +=
sprintf(buf + len, "post_blend_vd_v_end 0x%x.\n",
curpip_frame_par->VPP_post_blend_vd_v_end_);
len +=
sprintf(buf + len, "VPP_hd_start_lines_ 0x%x.\n",
curpip_frame_par->VPP_hd_start_lines_);
len +=
sprintf(buf + len, "VPP_hd_end_lines_ 0x%x.\n",
curpip_frame_par->VPP_hd_end_lines_);
len +=
sprintf(buf + len, "VPP_vd_start_lines_ 0x%x.\n",
curpip_frame_par->VPP_vd_start_lines_);
len +=
sprintf(buf + len, "VPP_vd_end_lines_ 0x%x.\n",
curpip_frame_par->VPP_vd_end_lines_);
len +=
sprintf(buf + len, "VPP_hsc_startp 0x%x.\n",
curpip_frame_par->VPP_hsc_startp);
len +=
sprintf(buf + len, "VPP_hsc_endp 0x%x.\n",
curpip_frame_par->VPP_hsc_endp);
len +=
sprintf(buf + len, "VPP_vsc_startp 0x%x.\n",
curpip_frame_par->VPP_vsc_startp);
len +=
sprintf(buf + len, "VPP_vsc_endp 0x%x.\n",
curpip_frame_par->VPP_vsc_endp);
return len;
}
#endif
static 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(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(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(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(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_RO(frame_addr),
__ATTR_RO(frame_canvas_width),
__ATTR_RO(frame_canvas_height),
__ATTR_RO(frame_width),
__ATTR_RO(frame_height),
__ATTR_RO(frame_org_width),
__ATTR_RO(frame_org_height),
__ATTR_RO(frame_render_ready),
__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(video_layer1_state),
__ATTR_RO(pic_mode_info),
#ifdef VIDEO_PIP
__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),
#endif
__ATTR_NULL
};
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_NULL
};
#ifdef CONFIG_PM
static int amvideo_class_suspend(struct device *dev, pm_message_t state)
{
#if 0
pm_state.event = state.event;
if (state.event == PM_EVENT_SUSPEND) {
pm_state.vpp_misc =
READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off);
DisableVideoLayer_NoDelay();
msleep(50);
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
&& !is_meson_mtvd_cpu()) {
vpu_delay_work_flag = 0;
}
/* #endif */
}
#endif
return 0;
}
static int amvideo_class_resume(struct device *dev)
{
#if 0
#define VPP_MISC_VIDEO_BITS_MASK \
((VPP_VD2_ALPHA_MASK << VPP_VD2_ALPHA_BIT) | \
VPP_VD2_PREBLEND | VPP_VD1_PREBLEND |\
VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | VPP_POSTBLEND_EN)\
if (pm_state.event == PM_EVENT_SUSPEND) {
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
&& !is_meson_mtvd_cpu()) {
switch_vpu_mem_pd_vmod(VPU_VIU_VD1,
pm_state.mem_pd_vd1);
switch_vpu_mem_pd_vmod(VPU_VIU_VD2,
pm_state.mem_pd_vd2);
switch_vpu_mem_pd_vmod(VPU_DI_POST,
pm_state.mem_pd_di_post);
}
/* #endif */
WRITE_VCBUS_REG(VPP_MISC + cur_dev->vpp_off,
(READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) &
(~VPP_MISC_VIDEO_BITS_MASK)) |
(pm_state.vpp_misc & VPP_MISC_VIDEO_BITS_MASK));
WRITE_VCBUS_REG(VPP_MISC +
cur_dev->vpp_off, pm_state.vpp_misc);
pm_state.event = -1;
if (debug_flag & DEBUG_FLAG_BLACKOUT) {
pr_info("%s write(VPP_MISC,%x)\n", __func__,
pm_state.vpp_misc);
}
}
#ifdef CONFIG_SCREEN_ON_EARLY
if (power_key_pressed) {
vout_pll_resume_early();
osd_resume_early();
resume_vout_early();
power_key_pressed = 0;
}
#endif
#endif
return 0;
}
#endif
static struct class amvideo_class = {
.name = AMVIDEO_CLASS_NAME,
.class_attrs = amvideo_class_attrs,
#ifdef CONFIG_PM
.suspend = amvideo_class_suspend,
.resume = amvideo_class_resume,
#endif
};
static struct class amvideo_poll_class = {
.name = AMVIDEO_POLL_CLASS_NAME,
.class_attrs = amvideo_poll_class_attrs,
};
#ifdef TV_REVERSE
static int __init vpp_axis_reverse(char *str)
{
unsigned char *ptr = str;
pr_info("%s: bootargs is %s\n", __func__, str);
if (strstr(ptr, "1"))
reverse = true;
else
reverse = false;
return 0;
}
__setup("video_reverse=", vpp_axis_reverse);
#endif
struct vframe_s *get_cur_dispbuf(void)
{
return cur_dispbuf;
}
#ifdef CONFIG_AM_VOUT
int vout_notify_callback(struct notifier_block *block, unsigned long cmd,
void *para)
{
const struct vinfo_s *info;
ulong flags;
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
if (cur_dev != &video_dev[0])
return 0;
#endif
switch (cmd) {
case VOUT_EVENT_MODE_CHANGE:
info = get_current_vinfo();
spin_lock_irqsave(&lock, flags);
vinfo = info;
/* pre-calculate vsync_pts_inc in 90k unit */
vsync_pts_inc = 90000 * vinfo->sync_duration_den /
vinfo->sync_duration_num;
vsync_pts_inc_scale = vinfo->sync_duration_den;
vsync_pts_inc_scale_base = vinfo->sync_duration_num;
spin_unlock_irqrestore(&lock, flags);
new_vmode = vinfo->mode;
break;
case VOUT_EVENT_OSD_PREBLEND_ENABLE:
break;
case VOUT_EVENT_OSD_DISP_AXIS:
break;
}
return 0;
}
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
int vout2_notify_callback(struct notifier_block *block, unsigned long cmd,
void *para)
{
const struct vinfo_s *info;
ulong flags;
if (cur_dev != &video_dev[1])
return 0;
switch (cmd) {
case VOUT_EVENT_MODE_CHANGE:
info = get_current_vinfo2();
spin_lock_irqsave(&lock, flags);
vinfo = info;
/* pre-calculate vsync_pts_inc in 90k unit */
vsync_pts_inc = 90000 * vinfo->sync_duration_den /
vinfo->sync_duration_num;
vsync_pts_inc_scale = vinfo->sync_duration_den;
vsync_pts_inc_scale_base = vinfo->sync_duration_num;
spin_unlock_irqrestore(&lock, flags);
break;
case VOUT_EVENT_OSD_PREBLEND_ENABLE:
break;
case VOUT_EVENT_OSD_DISP_AXIS:
break;
}
return 0;
}
#endif
static struct notifier_block vout_notifier = {
.notifier_call = vout_notify_callback,
};
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
static struct notifier_block vout2_notifier = {
.notifier_call = vout2_notify_callback,
};
#endif
static void vout_hook(void)
{
vout_register_client(&vout_notifier);
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
vout2_register_client(&vout2_notifier);
#endif
vinfo = get_current_vinfo();
if (!vinfo) {
#if DEBUG_TMP
set_current_vmode(VMODE_720P);
#endif
vinfo = get_current_vinfo();
}
if (vinfo) {
vsync_pts_inc = 90000 * vinfo->sync_duration_den /
vinfo->sync_duration_num;
vsync_pts_inc_scale = vinfo->sync_duration_den;
vsync_pts_inc_scale_base = vinfo->sync_duration_num;
old_vmode = new_vmode = vinfo->mode;
}
#ifdef CONFIG_AM_VIDEO_LOG
if (vinfo) {
amlog_mask(LOG_MASK_VINFO, "vinfo = %p\n", vinfo);
amlog_mask(LOG_MASK_VINFO, "display platform %s:\n",
vinfo->name);
amlog_mask(LOG_MASK_VINFO, "\tresolution %d x %d\n",
vinfo->width, vinfo->height);
amlog_mask(LOG_MASK_VINFO, "\taspect ratio %d : %d\n",
vinfo->aspect_ratio_num, vinfo->aspect_ratio_den);
amlog_mask(LOG_MASK_VINFO, "\tsync duration %d : %d\n",
vinfo->sync_duration_num, vinfo->sync_duration_den);
}
#endif
}
#endif
static int amvideo_notify_callback(
struct notifier_block *block,
unsigned long cmd,
void *para)
{
u32 *p, val;
switch (cmd) {
case AMVIDEO_UPDATE_OSD_MODE:
p = (u32 *)para;
if (!update_osd_vpp_misc)
osd_vpp_misc_mask = p[1];
val = osd_vpp_misc
& (~osd_vpp_misc_mask);
val |= (p[0] & osd_vpp_misc_mask);
osd_vpp_misc = val;
if (!update_osd_vpp_misc)
update_osd_vpp_misc = true;
break;
default:
break;
}
return 0;
}
static struct notifier_block amvideo_notifier = {
.notifier_call = amvideo_notify_callback,
};
static RAW_NOTIFIER_HEAD(amvideo_notifier_list);
int amvideo_register_client(struct notifier_block *nb)
{
return raw_notifier_chain_register(&amvideo_notifier_list, nb);
}
EXPORT_SYMBOL(amvideo_register_client);
int amvideo_unregister_client(struct notifier_block *nb)
{
return raw_notifier_chain_unregister(&amvideo_notifier_list, nb);
}
EXPORT_SYMBOL(amvideo_unregister_client);
int amvideo_notifier_call_chain(unsigned long val, void *v)
{
return raw_notifier_call_chain(&amvideo_notifier_list, val, v);
}
EXPORT_SYMBOL_GPL(amvideo_notifier_call_chain);
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
static void do_vpu_delay_work(struct work_struct *work)
{
unsigned long flags;
unsigned int r;
#if DEBUG_TMP
if (vpu_delay_work_flag & VPU_VIDEO_LAYER1_CHANGED) {
vpu_delay_work_flag &= ~VPU_VIDEO_LAYER1_CHANGED;
switch_set_state(&video1_state_sdev, !!video_enabled);
}
#endif
spin_lock_irqsave(&delay_work_lock, flags);
if (vpu_delay_work_flag & VPU_DELAYWORK_VPU_CLK) {
vpu_delay_work_flag &= ~VPU_DELAYWORK_VPU_CLK;
spin_unlock_irqrestore(&delay_work_lock, flags);
if (vpu_clk_level > 0)
request_vpu_clk_vmod(360000000, VPU_VIU_VD1);
else
release_vpu_clk_vmod(VPU_VIU_VD1);
spin_lock_irqsave(&delay_work_lock, flags);
}
r = READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off);
if (vpu_mem_power_off_count > 0) {
vpu_mem_power_off_count--;
if (vpu_mem_power_off_count == 0) {
if ((vpu_delay_work_flag &
VPU_DELAYWORK_MEM_POWER_OFF_VD1)
&& ((r & VPP_VD1_PREBLEND) == 0)) {
vpu_delay_work_flag &=
~VPU_DELAYWORK_MEM_POWER_OFF_VD1;
switch_vpu_mem_pd_vmod(
VPU_VIU_VD1,
VPU_MEM_POWER_DOWN);
switch_vpu_mem_pd_vmod(
VPU_AFBC_DEC,
VPU_MEM_POWER_DOWN);
switch_vpu_mem_pd_vmod(
VPU_DI_POST,
VPU_MEM_POWER_DOWN);
if (!legacy_vpp)
switch_vpu_mem_pd_vmod(
VPU_VD1_SCALE,
VPU_MEM_POWER_DOWN);
}
if ((vpu_delay_work_flag &
VPU_DELAYWORK_MEM_POWER_OFF_VD2)
&& ((r & VPP_VD2_PREBLEND) == 0)) {
vpu_delay_work_flag &=
~VPU_DELAYWORK_MEM_POWER_OFF_VD2;
switch_vpu_mem_pd_vmod(
VPU_VIU_VD2,
VPU_MEM_POWER_DOWN);
switch_vpu_mem_pd_vmod(
VPU_AFBC_DEC1,
VPU_MEM_POWER_DOWN);
if (!legacy_vpp)
switch_vpu_mem_pd_vmod(
VPU_VD2_SCALE,
VPU_MEM_POWER_DOWN);
}
if ((vpu_delay_work_flag &
VPU_DELAYWORK_MEM_POWER_OFF_PROT)
&& ((r & VPP_VD1_PREBLEND) == 0)) {
vpu_delay_work_flag &=
~VPU_DELAYWORK_MEM_POWER_OFF_PROT;
}
}
}
spin_unlock_irqrestore(&delay_work_lock, flags);
}
#endif
/*********************************************************/
struct device *get_video_device(void)
{
return amvideo_dev;
}
static int __init video_early_init(void)
{
/* todo: move this to clock tree, enable VPU clock */
/* WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,*/
/*(1<<9) | (1<<8) | (3)); // fclk_div3/4 = ~200M */
/* WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,*/
/*(3<<9) | (1<<8) | (0)); // fclk_div7/1 = 364M*/
/*moved to vpu.c, default config by dts */
u32 cur_hold_line;
if (!legacy_vpp) {
WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x1000,
VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID);
WRITE_VCBUS_REG_BITS(
VPP_MATRIX_CTRL, 0, 10, 5);
} else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB))
WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff,
VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID);
WRITE_VCBUS_REG(VPP_PREBLEND_VD1_H_START_END, 4096);
WRITE_VCBUS_REG(VPP_BLEND_VD2_H_START_END, 4096);
if (is_meson_txl_cpu() || is_meson_txlx_cpu()) {
/* fifo max size on txl :128*3=384[0x180] */
WRITE_VCBUS_REG(
VD1_IF0_LUMA_FIFO_SIZE + cur_dev->viu_off, 0x180);
WRITE_VCBUS_REG(
VD2_IF0_LUMA_FIFO_SIZE + cur_dev->viu_off, 0x180);
}
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x800,
VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID);
/*
*WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 1, 12, 2);
*select vdisp_mmc_arb for VIU2_OSD1 request
*/
WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 2, 12, 2);
/* select vdin_mmc_arb for VIU2_OSD1 request */
#endif
/* default 10bit setting for gxm */
if (is_meson_gxm_cpu()) {
WRITE_VCBUS_REG_BITS(VIU_MISC_CTRL1, 0xff, 16, 8);
WRITE_VCBUS_REG(VPP_DOLBY_CTRL, 0x22000);
/*
*default setting is black for dummy data1& dumy data0,
*for dummy data1 the y/cb/cr data width is 10bit on gxm,
*for dummy data the y/cb/cr data width is 8bit but
*vpp_dummy_data will be left shift 2bit auto on gxm!!!
*/
WRITE_VCBUS_REG(VPP_DUMMY_DATA1, 0x1020080);
WRITE_VCBUS_REG(VPP_DUMMY_DATA, 0x42020);
} else if (is_meson_txlx_cpu() ||
cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
/*black 10bit*/
WRITE_VCBUS_REG(VPP_DUMMY_DATA, 0x4080200);
}
/* temp: enable VPU arb mem */
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB)
switch_vpu_mem_pd_vmod(VPU_VPU_ARB, VPU_MEM_POWER_ON);
/*disable sr default when power up*/
WRITE_VCBUS_REG(VPP_SRSHARP0_CTRL, 0);
WRITE_VCBUS_REG(VPP_SRSHARP1_CTRL, 0);
cur_hold_line = READ_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off);
cur_hold_line = cur_hold_line & 0xff;
if (cur_hold_line > 0x1f)
vpp_hold_line = 0x1f;
else
vpp_hold_line = cur_hold_line;
/* Temp force set dmc */
if (!legacy_vpp) {
WRITE_DMCREG(
DMC_AM0_CHAN_CTRL,
0x8ff403cf);
/* for vd1 & vd2 dummy alpha*/
WRITE_VCBUS_REG(
VPP_POST_BLEND_DUMMY_ALPHA,
0x7fffffff);
WRITE_VCBUS_REG_BITS(
VPP_MISC1, 0x100, 0, 9);
}
if (is_meson_tl1_cpu()) {
/* force bypass dolby for TL1, no dolby function */
WRITE_VCBUS_REG_BITS(
DOLBY_PATH_CTRL, 0xf, 0, 6);
/* disable latch for sr core0/1 scaler */
WRITE_VCBUS_REG_BITS(
SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1);
WRITE_VCBUS_REG_BITS(
SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1);
}
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B))
WRITE_VCBUS_REG_BITS(
SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1);
return 0;
}
static struct mconfig video_configs[] = {
MC_PI32("pause_one_3d_fl_frame", &pause_one_3d_fl_frame),
MC_PI32("debug_flag", &debug_flag),
MC_PU32("force_3d_scaler", &force_3d_scaler),
MC_PU32("video_3d_format", &video_3d_format),
MC_PI32("vsync_enter_line_max", &vsync_enter_line_max),
MC_PI32("vsync_exit_line_max", &vsync_exit_line_max),
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
MC_PI32("vsync_rdma_line_max", &vsync_rdma_line_max),
#endif
MC_PU32("underflow", &underflow),
MC_PU32("next_peek_underflow", &next_peek_underflow),
MC_PU32("smooth_sync_enable", &smooth_sync_enable),
MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo),
#ifdef CONFIG_AM_VIDEO2
MC_PI32("video_play_clone_rate", &video_play_clone_rate),
MC_PI32("android_clone_rate", &android_clone_rate),
MC_PI32("video_play_clone_rate", &video_play_clone_rate),
MC_PI32("android_clone_rate", &android_clone_rate),
MC_PI32("noneseamless_play_clone_rate", &noneseamless_play_clone_rate),
#endif
MC_PU32("smooth_sync_enable", &smooth_sync_enable),
MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo),
MC_PI32("cur_dev_idx", &cur_dev_idx),
MC_PU32("new_frame_count", &new_frame_count),
MC_PU32("omx_pts", &omx_pts),
MC_PU32("omx_pts_set_index", &omx_pts_set_index),
MC_PBOOL("omx_run", &omx_run),
MC_PU32("omx_version", &omx_version),
MC_PU32("omx_info", &omx_info),
MC_PI32("omx_need_drop_frame_num", &omx_need_drop_frame_num),
MC_PBOOL("omx_drop_done", &omx_drop_done),
MC_PI32("omx_pts_interval_upper", &omx_pts_interval_upper),
MC_PI32("omx_pts_interval_lower", &omx_pts_interval_lower),
MC_PBOOL("bypass_pps", &bypass_pps),
MC_PBOOL("platform_type", &platform_type),
MC_PU32("process_3d_type", &process_3d_type),
MC_PU32("omx_pts", &omx_pts),
MC_PU32("framepacking_support", &framepacking_support),
MC_PU32("framepacking_width", &framepacking_width),
MC_PU32("framepacking_height", &framepacking_height),
MC_PU32("framepacking_blank", &framepacking_blank),
MC_PU32("video_seek_flag", &video_seek_flag),
MC_PU32("slowsync_repeat_enable", &slowsync_repeat_enable),
MC_PU32("toggle_count", &toggle_count),
MC_PBOOL("show_first_frame_nosync", &show_first_frame_nosync),
#ifdef TV_REVERSE
MC_PBOOL("reverse", &reverse),
#endif
};
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
static void video_early_suspend(struct early_suspend *h)
{
DisableVideoLayer();
DisableVideoLayer2();
pr_info("video_early_suspend ok\n");
}
static void video_late_resume(struct early_suspend *h)
{
pr_info("video_late_resume ok\n");
};
static struct early_suspend video_early_suspend_handler = {
.suspend = video_early_suspend,
.resume = video_late_resume,
};
#endif
static int amvideom_probe(struct platform_device *pdev)
{
int ret = 0;
video_early_init();
DisableVideoLayer();
DisableVideoLayer2();
/* get interrupt resource */
video_vsync = platform_get_irq_byname(pdev, "vsync");
if (video_vsync == -ENXIO) {
pr_info("cannot get amvideom irq resource\n");
return video_vsync;
}
pr_info("amvideom vsync irq: %d\n", video_vsync);
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
register_early_suspend(&video_early_suspend_handler);
#endif
return ret;
}
static int amvideom_remove(struct platform_device *pdev)
{
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
unregister_early_suspend(&video_early_suspend_handler);
#endif
return 0;
}
static const struct of_device_id amlogic_amvideom_dt_match[] = {
{
.compatible = "amlogic, amvideom",
},
{},
};
static struct platform_driver amvideom_driver = {
.probe = amvideom_probe,
.remove = amvideom_remove,
.driver = {
.name = "amvideom",
.of_match_table = amlogic_amvideom_dt_match,
}
};
static int __init video_init(void)
{
int r = 0, i;
/*
*#ifdef CONFIG_ARCH_MESON1
*ulong clk = clk_get_rate(clk_get_sys("clk_other_pll", NULL));
*#elif !defined(CONFIG_ARCH_MESON3) && !defined(CONFIG_ARCH_MESON6)
*ulong clk = clk_get_rate(clk_get_sys("clk_misc_pll", NULL));
*#endif
*/
#ifdef CONFIG_ARCH_MESON1
no to here ulong clk =
clk_get_rate(clk_get_sys("clk_other_pll", NULL));
#elif defined(CONFIG_ARCH_MESON2)
not to here ulong clk =
clk_get_rate(clk_get_sys("clk_misc_pll", NULL));
#endif
/* #if !defined(CONFIG_ARCH_MESON3) && !defined(CONFIG_ARCH_MESON6) */
#if 0 /* MESON_CPU_TYPE <= MESON_CPU_TYPE_MESON2 */
/* MALI clock settings */
if ((clk <= 750000000) && (clk >= 600000000)) {
WRITE_VCBUS_REG(HHI_MALI_CLK_CNTL,
(2 << 9) | /* select misc pll as clock source */
(1 << 8) | /* enable clock gating */
(2 << 0)); /* Misc clk / 3 */
} else {
WRITE_VCBUS_REG(HHI_MALI_CLK_CNTL,
(3 << 9) | /* select DDR clock as clock source */
(1 << 8) | /* enable clock gating */
(1 << 0)); /* DDR clk / 2 */
}
#endif
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
cur_dev->viu_off = 0x3200 - 0x1a50;
legacy_vpp = false;
}
if (platform_driver_register(&amvideom_driver)) {
pr_info("failed to amvideom driver!\n");
return -ENODEV;
}
/* check super scaler support status */
vpp_super_scaler_support();
/* adaptive config bypass ratio */
vpp_bypass_ratio_config();
#ifndef CONFIG_AM_VIDEO2
/*DisableVPP2VideoLayer();*/
#endif
cur_dispbuf = NULL;
cur_dispbuf2 = NULL;
amvideo_register_client(&amvideo_notifier);
#ifdef FIQ_VSYNC
/* enable fiq bridge */
vsync_fiq_bridge.handle = vsync_bridge_isr;
vsync_fiq_bridge.key = (u32) vsync_bridge_isr;
vsync_fiq_bridge.name = "vsync_bridge_isr";
r = register_fiq_bridge_handle(&vsync_fiq_bridge);
if (r) {
amlog_level(LOG_LEVEL_ERROR,
"video fiq bridge register error.\n");
r = -ENOENT;
goto err0;
}
#endif
/* sysfs node creation */
r = class_register(&amvideo_poll_class);
if (r) {
amlog_level(LOG_LEVEL_ERROR, "create video_poll class fail.\n");
#ifdef FIQ_VSYNC
free_irq(BRIDGE_IRQ, (void *)video_dev_id);
#else
free_irq(INT_VIU_VSYNC, (void *)video_dev_id);
#endif
goto err1;
}
r = class_register(&amvideo_class);
if (r) {
amlog_level(LOG_LEVEL_ERROR, "create video class fail.\n");
#ifdef FIQ_VSYNC
free_irq(BRIDGE_IRQ, (void *)video_dev_id);
#else
free_irq(INT_VIU_VSYNC, (void *)video_dev_id);
#endif
goto err1;
}
/* create video device */
r = register_chrdev(AMVIDEO_MAJOR, "amvideo", &amvideo_fops);
if (r < 0) {
amlog_level(LOG_LEVEL_ERROR,
"Can't register major for amvideo device\n");
goto err2;
}
r = register_chrdev(0, "amvideo_poll", &amvideo_poll_fops);
if (r < 0) {
amlog_level(LOG_LEVEL_ERROR,
"Can't register major for amvideo_poll device\n");
goto err3;
}
amvideo_poll_major = r;
amvideo_dev = device_create(&amvideo_class, NULL,
MKDEV(AMVIDEO_MAJOR, 0), NULL, DEVICE_NAME);
if (IS_ERR(amvideo_dev)) {
amlog_level(LOG_LEVEL_ERROR, "Can't create amvideo device\n");
goto err4;
}
amvideo_poll_dev = device_create(&amvideo_poll_class, NULL,
MKDEV(amvideo_poll_major, 0), NULL, "amvideo_poll");
if (IS_ERR(amvideo_poll_dev)) {
amlog_level(LOG_LEVEL_ERROR,
"Can't create amvideo_poll device\n");
goto err5;
}
/* make vd1 below vd2 */
for (i = 0; i < MAX_VD_LAYERS; i++) {
vpp_disp_info_init(&glayer_info[i], i);
memset(&gPic_info[i], 0, sizeof(struct vframe_pic_mode_s));
glayer_info[i].wide_mode = 1;
glayer_info[i].zorder = reference_zorder - 2 + i;
glayer_info[i].cur_sel_port = i;
glayer_info[i].last_sel_port = i;
}
if (legacy_vpp)
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
layer_cap =
LAYER1_AFBC |
LAYER1_SCALER |
LAYER1_AVAIL |
LAYER0_AFBC |
LAYER0_SCALER |
LAYER0_AVAIL;
init_waitqueue_head(&amvideo_trick_wait);
init_waitqueue_head(&amvideo_event_wait);
INIT_WORK(&vpu_delay_work, do_vpu_delay_work);
#ifdef CONFIG_AM_VOUT
vout_hook();
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
dispbuf_to_put_num = DISPBUF_TO_PUT_MAX;
while (dispbuf_to_put_num > 0) {
dispbuf_to_put_num--;
dispbuf_to_put[dispbuf_to_put_num] = NULL;
}
disp_canvas[0][0] =
(disp_canvas_index[0][2] << 16) | (disp_canvas_index[0][1] << 8) |
disp_canvas_index[0][0];
disp_canvas[0][1] =
(disp_canvas_index[0][5] << 16) | (disp_canvas_index[0][4] << 8) |
disp_canvas_index[0][3];
disp_canvas[1][0] =
(disp_canvas_index[1][2] << 16) | (disp_canvas_index[1][1] << 8) |
disp_canvas_index[1][0];
disp_canvas[1][1] =
(disp_canvas_index[1][5] << 16) | (disp_canvas_index[1][4] << 8) |
disp_canvas_index[1][3];
#else
disp_canvas[0] =
(disp_canvas_index[2] << 16) | (disp_canvas_index[1] << 8) |
disp_canvas_index[0];
disp_canvas[1] =
(disp_canvas_index[5] << 16) | (disp_canvas_index[4] << 8) |
disp_canvas_index[3];
#endif
vsync_fiq_up();
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
vsync2_fiq_up();
#endif
vf_receiver_init(&video_vf_recv, RECEIVER_NAME, &video_vf_receiver,
NULL);
vf_reg_receiver(&video_vf_recv);
#ifdef VIDEO_PIP
vf_receiver_init(
&videopip_vf_recv, RECEIVERPIP_NAME,
&videopip_vf_receiver, NULL);
vf_reg_receiver(&videopip_vf_recv);
#endif
#if DEBUG_TMP
switch_dev_register(&video1_state_sdev);
switch_set_state(&video1_state_sdev, 0);
#endif
video_keeper_init();
#ifdef CONFIG_AM_VIDEO2
set_clone_frame_rate(android_clone_rate, 0);
#endif
REG_PATH_CONFIGS("media.video", video_configs);
video_debugfs_init();
return 0;
err5:
device_destroy(&amvideo_class, MKDEV(AMVIDEO_MAJOR, 0));
err4:
unregister_chrdev(amvideo_poll_major, "amvideo_poll");
err3:
unregister_chrdev(AMVIDEO_MAJOR, DEVICE_NAME);
err2:
#ifdef FIQ_VSYNC
unregister_fiq_bridge_handle(&vsync_fiq_bridge);
#endif
class_unregister(&amvideo_class);
err1:
class_unregister(&amvideo_poll_class);
#ifdef FIQ_VSYNC
err0:
#endif
amvideo_unregister_client(&amvideo_notifier);
platform_driver_unregister(&amvideom_driver);
return r;
}
static void __exit video_exit(void)
{
video_debugfs_exit();
vf_unreg_receiver(&video_vf_recv);
#ifdef VIDEO_PIP
vf_unreg_receiver(&videopip_vf_recv);
#endif
DisableVideoLayer();
DisableVideoLayer2();
vsync_fiq_down();
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
vsync2_fiq_down();
#endif
device_destroy(&amvideo_class, MKDEV(AMVIDEO_MAJOR, 0));
device_destroy(&amvideo_poll_class, MKDEV(amvideo_poll_major, 0));
unregister_chrdev(AMVIDEO_MAJOR, DEVICE_NAME);
unregister_chrdev(amvideo_poll_major, "amvideo_poll");
#ifdef FIQ_VSYNC
unregister_fiq_bridge_handle(&vsync_fiq_bridge);
#endif
class_unregister(&amvideo_class);
class_unregister(&amvideo_poll_class);
amvideo_unregister_client(&amvideo_notifier);
}
MODULE_PARM_DESC(debug_flag, "\n debug_flag\n");
module_param(debug_flag, uint, 0664);
#ifdef TV_3D_FUNCTION_OPEN
MODULE_PARM_DESC(force_3d_scaler, "\n force_3d_scaler\n");
module_param(force_3d_scaler, uint, 0664);
MODULE_PARM_DESC(video_3d_format, "\n video_3d_format\n");
module_param(video_3d_format, uint, 0664);
#endif
MODULE_PARM_DESC(vsync_enter_line_max, "\n vsync_enter_line_max\n");
module_param(vsync_enter_line_max, uint, 0664);
MODULE_PARM_DESC(vsync_exit_line_max, "\n vsync_exit_line_max\n");
module_param(vsync_exit_line_max, uint, 0664);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
MODULE_PARM_DESC(vsync_rdma_line_max, "\n vsync_rdma_line_max\n");
module_param(vsync_rdma_line_max, uint, 0664);
#endif
module_param(underflow, uint, 0664);
MODULE_PARM_DESC(underflow, "\n Underflow count\n");
module_param(next_peek_underflow, uint, 0664);
MODULE_PARM_DESC(skip, "\n Underflow count\n");
module_param(hdmiin_frame_check, uint, 0664);
MODULE_PARM_DESC(hdmiin_frame_check, "\n hdmiin_frame_check\n");
module_param(step_enable, uint, 0664);
MODULE_PARM_DESC(step_enable, "\n step_enable\n");
module_param(step_flag, uint, 0664);
MODULE_PARM_DESC(step_flag, "\n step_flag\n");
/*arch_initcall(video_early_init);*/
module_init(video_init);
module_exit(video_exit);
MODULE_PARM_DESC(smooth_sync_enable, "\n smooth_sync_enable\n");
module_param(smooth_sync_enable, uint, 0664);
MODULE_PARM_DESC(hdmi_in_onvideo, "\n hdmi_in_onvideo\n");
module_param(hdmi_in_onvideo, uint, 0664);
#ifdef CONFIG_AM_VIDEO2
MODULE_PARM_DESC(video_play_clone_rate, "\n video_play_clone_rate\n");
module_param(video_play_clone_rate, uint, 0664);
MODULE_PARM_DESC(android_clone_rate, "\n android_clone_rate\n");
module_param(android_clone_rate, uint, 0664);
MODULE_PARM_DESC(noneseamless_play_clone_rate,
"\n noneseamless_play_clone_rate\n");
module_param(noneseamless_play_clone_rate, uint, 0664);
#endif
MODULE_PARM_DESC(vsync_count, "\n vsync_count\n");
module_param(vsync_count, uint, 0664);
MODULE_PARM_DESC(cur_dev_idx, "\n cur_dev_idx\n");
module_param(cur_dev_idx, uint, 0664);
MODULE_PARM_DESC(new_frame_count, "\n new_frame_count\n");
module_param(new_frame_count, uint, 0664);
MODULE_PARM_DESC(first_frame_toggled, "\n first_frame_toggled\n");
module_param(first_frame_toggled, uint, 0664);
MODULE_PARM_DESC(omx_pts, "\n omx_pts\n");
module_param(omx_pts, uint, 0664);
MODULE_PARM_DESC(omx_run, "\n omx_run\n");
module_param(omx_run, bool, 0664);
MODULE_PARM_DESC(omx_pts_set_index, "\n omx_pts_set_index\n");
module_param(omx_pts_set_index, uint, 0664);
MODULE_PARM_DESC(omx_version, "\n omx_version\n");
module_param(omx_version, uint, 0664);
MODULE_PARM_DESC(omx_info, "\n omx_info\n");
module_param(omx_info, uint, 0664);
MODULE_PARM_DESC(omx_need_drop_frame_num, "\n omx_need_drop_frame_num\n");
module_param(omx_need_drop_frame_num, int, 0664);
MODULE_PARM_DESC(omx_drop_done, "\n omx_drop_done\n");
module_param(omx_drop_done, bool, 0664);
MODULE_PARM_DESC(omx_pts_interval_upper, "\n omx_pts_interval\n");
module_param(omx_pts_interval_upper, int, 0664);
MODULE_PARM_DESC(omx_pts_interval_lower, "\n omx_pts_interval\n");
module_param(omx_pts_interval_lower, int, 0664);
MODULE_PARM_DESC(drop_frame_count, "\n drop_frame_count\n");
module_param(drop_frame_count, int, 0664);
MODULE_PARM_DESC(receive_frame_count, "\n receive_frame_count\n");
module_param(receive_frame_count, int, 0664);
MODULE_PARM_DESC(display_frame_count, "\n display_frame_count\n");
module_param(display_frame_count, int, 0664);
module_param(frame_detect_time, uint, 0664);
MODULE_PARM_DESC(frame_detect_time, "\n frame_detect_time\n");
module_param(frame_detect_flag, uint, 0664);
MODULE_PARM_DESC(frame_detect_flag, "\n frame_detect_flag\n");
module_param(frame_detect_fps, uint, 0664);
MODULE_PARM_DESC(frame_detect_fps, "\n frame_detect_fps\n");
module_param(frame_detect_receive_count, uint, 0664);
MODULE_PARM_DESC(frame_detect_receive_count, "\n frame_detect_receive_count\n");
module_param(frame_detect_drop_count, uint, 0664);
MODULE_PARM_DESC(frame_detect_drop_count, "\n frame_detect_drop_count\n");
MODULE_PARM_DESC(bypass_pps, "\n pps_bypass\n");
module_param(bypass_pps, bool, 0664);
MODULE_PARM_DESC(platform_type, "\n platform_type\n");
module_param(platform_type, bool, 0664);
MODULE_PARM_DESC(process_3d_type, "\n process_3d_type\n");
module_param(process_3d_type, uint, 0664);
MODULE_PARM_DESC(framepacking_support, "\n framepacking_support\n");
module_param(framepacking_support, uint, 0664);
MODULE_PARM_DESC(framepacking_width, "\n framepacking_width\n");
module_param(framepacking_width, uint, 0664);
MODULE_PARM_DESC(framepacking_height, "\n framepacking_height\n");
module_param(framepacking_height, uint, 0664);
MODULE_PARM_DESC(framepacking_blank, "\n framepacking_blank\n");
module_param(framepacking_blank, uint, 0664);
MODULE_PARM_DESC(bypass_cm, "\n bypass_cm\n");
module_param(bypass_cm, bool, 0664);
#ifdef TV_REVERSE
module_param(reverse, bool, 0644);
MODULE_PARM_DESC(reverse, "reverse /disable reverse");
#endif
MODULE_PARM_DESC(toggle_count, "\n toggle count\n");
module_param(toggle_count, uint, 0664);
MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n");
module_param(vpp_hold_line, uint, 0664);
MODULE_PARM_DESC(stop_update, "\n stop_update\n");
module_param(stop_update, uint, 0664);
MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n");
module_param(reference_zorder, uint, 0664);
MODULE_DESCRIPTION("AMLOGIC video output driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");