506 lines
14 KiB
C
506 lines
14 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
|
/*
|
|
* Copyright (c) 2025 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _DI_H
|
|
#define _DI_H
|
|
#include <linux/cdev.h>
|
|
#include <linux/types.h>
|
|
#include <linux/amlogic/media/vfm/vframe.h>
|
|
#include <linux/amlogic/media/video_sink/video.h>
|
|
#include <linux/amlogic/media/rdma/rdma_mgr.h>
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/atomic.h>
|
|
#include "deinterlace_hw.h"
|
|
#include "nr_drv.h"
|
|
#include "../di_local/di_local.h"
|
|
/*trigger_pre_di_process param*/
|
|
#define TRIGGER_PRE_BY_PUT 'p'
|
|
#define TRIGGER_PRE_BY_DE_IRQ 'i'
|
|
#define TRIGGER_PRE_BY_UNREG 'u'
|
|
/*di_timer_handle*/
|
|
#define TRIGGER_PRE_BY_TIMER 't'
|
|
#define TRIGGER_PRE_BY_FORCE_UNREG 'f'
|
|
#define TRIGGER_PRE_BY_VFRAME_READY 'r'
|
|
#define TRIGGER_PRE_BY_PROVIDER_UNREG 'n'
|
|
#define TRIGGER_PRE_BY_DEBUG_DISABLE 'd'
|
|
#define TRIGGER_PRE_BY_PROVIDER_REG 'R'
|
|
|
|
#define DI_RUN_FLAG_RUN 0
|
|
#define DI_RUN_FLAG_PAUSE 1
|
|
#define DI_RUN_FLAG_STEP 2
|
|
#define DI_RUN_FLAG_STEP_DONE 3
|
|
|
|
#define USED_LOCAL_BUF_MAX 3
|
|
#define BYPASS_GET_MAX_BUF_NUM 9
|
|
|
|
/* buffer management related */
|
|
#define MAX_IN_BUF_NUM 20
|
|
#define MAX_LOCAL_BUF_NUM 10
|
|
#define MAX_POST_BUF_NUM 16
|
|
|
|
#define VFRAME_TYPE_IN 1
|
|
#define VFRAME_TYPE_LOCAL 2
|
|
#define VFRAME_TYPE_POST 3
|
|
#define VFRAME_TYPE_NUM 3
|
|
|
|
/*vframe define*/
|
|
#define vframe_t struct vframe_s
|
|
|
|
/* canvas defination */
|
|
#define DI_USE_FIXED_CANVAS_IDX
|
|
//#define DET3D
|
|
#undef SUPPORT_MPEG_TO_VDIN
|
|
#define CLK_TREE_SUPPORT
|
|
#ifndef CONFIG_AMLOGIC_MEDIA_RDMA
|
|
#ifndef VSYNC_WR_MPEG_REG
|
|
#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val)
|
|
#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \
|
|
aml_vcbus_update_bits(adr, ((1<<len)-1)<<start, val<<start)
|
|
#define VSYNC_RD_MPEG_REG(adr) aml_read_vcbus(adr)
|
|
#endif
|
|
#endif
|
|
|
|
#define IS_VDIN_SRC(src) ( \
|
|
(src == VFRAME_SOURCE_TYPE_TUNER) || \
|
|
(src == VFRAME_SOURCE_TYPE_CVBS) || \
|
|
(src == VFRAME_SOURCE_TYPE_COMP) || \
|
|
(src == VFRAME_SOURCE_TYPE_HDMI))
|
|
|
|
#define IS_I_SRC(vftype) (vftype & VIDTYPE_INTERLACE_BOTTOM)
|
|
|
|
#define IS_COMP_MODE(vftype) (vftype & VIDTYPE_COMPRESS)
|
|
|
|
enum process_fun_index_e {
|
|
PROCESS_FUN_NULL = 0,
|
|
PROCESS_FUN_DI,
|
|
PROCESS_FUN_PD,
|
|
PROCESS_FUN_PROG,
|
|
PROCESS_FUN_BOB
|
|
};
|
|
#define process_fun_index_t enum process_fun_index_e
|
|
|
|
enum canvas_idx_e {
|
|
NR_CANVAS,
|
|
MTN_CANVAS,
|
|
MV_CANVAS,
|
|
};
|
|
#define pulldown_mode_t enum pulldown_mode_e
|
|
struct di_buf_s {
|
|
struct vframe_s *vframe;
|
|
int index; /* index in vframe_in_dup[] or vframe_in[],
|
|
* only for type of VFRAME_TYPE_IN
|
|
*/
|
|
int post_proc_flag; /* 0,no post di; 1, normal post di;
|
|
* 2, edge only; 3, dummy
|
|
*/
|
|
int new_format_flag;
|
|
int type;
|
|
int throw_flag;
|
|
int invert_top_bot_flag;
|
|
int seq;
|
|
int pre_ref_count; /* none zero, is used by mem_mif,
|
|
* chan2_mif, or wr_buf
|
|
*/
|
|
int post_ref_count; /* none zero, is used by post process */
|
|
int queue_index;
|
|
/*below for type of VFRAME_TYPE_LOCAL */
|
|
unsigned long nr_adr;
|
|
int nr_canvas_idx;
|
|
unsigned long mtn_adr;
|
|
int mtn_canvas_idx;
|
|
unsigned long cnt_adr;
|
|
int cnt_canvas_idx;
|
|
unsigned long mcinfo_adr;
|
|
int mcinfo_canvas_idx;
|
|
unsigned short *mcinfo_vaddr;
|
|
bool bflg_vmap;
|
|
unsigned long mcvec_adr;
|
|
int mcvec_canvas_idx;
|
|
struct mcinfo_pre_s {
|
|
unsigned int highvertfrqflg;
|
|
unsigned int motionparadoxflg;
|
|
unsigned int regs[26];/* reg 0x2fb0~0x2fc9 */
|
|
} curr_field_mcinfo;
|
|
/* blend window */
|
|
struct pulldown_detected_s
|
|
pd_config;
|
|
/* tff bff check result bit[1:0]*/
|
|
unsigned int privated;
|
|
unsigned int canvas_config_flag;
|
|
/* 0,configed; 1,config type 1 (prog);
|
|
* 2, config type 2 (interlace)
|
|
*/
|
|
unsigned int canvas_height;
|
|
unsigned int canvas_width[3];/* nr/mtn/mv */
|
|
process_fun_index_t process_fun_index;
|
|
int early_process_fun_index;
|
|
int left_right;/*1,left eye; 0,right eye in field alternative*/
|
|
/*below for type of VFRAME_TYPE_POST*/
|
|
struct di_buf_s *di_buf[2];
|
|
struct di_buf_s *di_buf_dup_p[5];
|
|
/* 0~4: n-2, n-1, n, n+1, n+2; n is the field to display*/
|
|
struct di_buf_s *di_wr_linked_buf;
|
|
/* debug for di-vf-get/put
|
|
* 1: after get
|
|
* 0: after put
|
|
*/
|
|
atomic_t di_cnt;
|
|
struct page *pages;
|
|
u32 width_bk;
|
|
};
|
|
#define RDMA_DET3D_IRQ 0x20
|
|
/* vdin0 rdma irq */
|
|
#define RDMA_DEINT_IRQ 0x2
|
|
#define RDMA_TABLE_SIZE ((PAGE_SIZE)<<1)
|
|
|
|
#define MAX_CANVAS_WIDTH 1920
|
|
#define MAX_CANVAS_HEIGHT 1088
|
|
|
|
|
|
/* #define DI_BUFFER_DEBUG */
|
|
|
|
#define DI_LOG_MTNINFO 0x02
|
|
#define DI_LOG_PULLDOWN 0x10
|
|
#define DI_LOG_BUFFER_STATE 0x20
|
|
#define DI_LOG_TIMESTAMP 0x100
|
|
#define DI_LOG_PRECISE_TIMESTAMP 0x200
|
|
#define DI_LOG_QUEUE 0x40
|
|
#define DI_LOG_VFRAME 0x80
|
|
|
|
|
|
#define QUEUE_LOCAL_FREE 0
|
|
#define QUEUE_IN_FREE 1
|
|
#define QUEUE_PRE_READY 2
|
|
#define QUEUE_POST_FREE 3
|
|
#define QUEUE_POST_READY 4
|
|
#define QUEUE_RECYCLE 5
|
|
#define QUEUE_DISPLAY 6
|
|
#define QUEUE_TMP 7
|
|
#define QUEUE_POST_DOING 8
|
|
#define QUEUE_NUM 9
|
|
|
|
#define VFM_NAME "deinterlace"
|
|
|
|
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
|
|
extern void enable_rdma(int enable_flag);
|
|
extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val);
|
|
extern int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len);
|
|
extern u32 VSYNC_RD_MPEG_REG(u32 adr);
|
|
extern bool is_vsync_rdma_enable(void);
|
|
#else
|
|
#ifndef VSYNC_WR_MPEG_REG
|
|
#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val)
|
|
#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \
|
|
aml_vcbus_update_bits(adr, ((1<<len)-1)<<start, val<<start)
|
|
#define VSYNC_RD_MPEG_REG(adr) aml_read_vcbus(adr)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#define DI_COUNT 1
|
|
#define DI_MAP_FLAG 0x1
|
|
#define DI_SUSPEND_FLAG 0x2
|
|
#define DI_LOAD_REG_FLAG 0x4
|
|
#define DI_VPU_CLKB_SET 0x8
|
|
|
|
#define TABLE_LEN_MAX 10000
|
|
#define TABLE_FLG_END (0xfffffffe)
|
|
|
|
/******************************************
|
|
* patch for TV-10258 multiwave group issue
|
|
*****************************************/
|
|
#define DI_PATCH_MOV_MAX_NUB 5
|
|
|
|
struct di_patch_mov_d_s {
|
|
unsigned int val;
|
|
unsigned int mask;
|
|
bool en;
|
|
};
|
|
|
|
struct di_patch_mov_s {
|
|
unsigned int reg_addr[DI_PATCH_MOV_MAX_NUB];
|
|
struct di_patch_mov_d_s val_db[DI_PATCH_MOV_MAX_NUB];
|
|
struct di_patch_mov_d_s val_pq[DI_PATCH_MOV_MAX_NUB];
|
|
int mode;/*-1 : not set; 0: set from db, 1: set from pq*/
|
|
bool en_support;
|
|
bool update;
|
|
unsigned int nub;
|
|
};
|
|
|
|
bool di_patch_mov_db(unsigned int addr, unsigned int val);
|
|
|
|
struct di_dev_s {
|
|
dev_t devt;
|
|
struct cdev cdev; /* The cdev structure */
|
|
struct device *dev;
|
|
struct platform_device *pdev;
|
|
struct task_struct *task;
|
|
struct clk *vpu_clkb;
|
|
unsigned long clkb_max_rate;
|
|
unsigned long clkb_min_rate;
|
|
struct list_head pq_table_list;
|
|
atomic_t pq_flag;
|
|
unsigned char di_event;
|
|
unsigned int pre_irq;
|
|
unsigned int post_irq;
|
|
unsigned int flags;
|
|
unsigned long jiffy;
|
|
unsigned long mem_start;
|
|
unsigned int mem_size;
|
|
unsigned int buffer_size;
|
|
unsigned int post_buffer_size;
|
|
unsigned int buf_num_avail;
|
|
int rdma_handle;
|
|
/* is support nr10bit */
|
|
unsigned int nr10bit_support;
|
|
/* is DI support post wr to mem for OMX */
|
|
unsigned int post_wr_support;
|
|
unsigned int nrds_enable;
|
|
unsigned int pps_enable;
|
|
u32 h_sc_down_en;/*sm1, tm2 ...*/
|
|
/*struct mutex cma_mutex;*/
|
|
unsigned int flag_cma;
|
|
struct page *total_pages;
|
|
atomic_t mem_flag;
|
|
struct dentry *dbg_root; /*dbg_fs*/
|
|
struct di_patch_mov_s mov;
|
|
struct vpu_dev_s *di_vpu_clk_gate_dev;
|
|
struct vpu_dev_s *di_vpu_pd_dec;
|
|
struct vpu_dev_s *di_vpu_pd_dec1;
|
|
struct vpu_dev_s *di_vpu_pd_vd1;
|
|
struct vpu_dev_s *di_vpu_pd_post;
|
|
u32 instance_id; /* di_instance_id; */
|
|
};
|
|
|
|
struct di_pre_stru_s {
|
|
/* pre input */
|
|
struct DI_MIF_s di_inp_mif;
|
|
struct DI_MIF_s di_mem_mif;
|
|
struct DI_MIF_s di_chan2_mif;
|
|
struct di_buf_s *di_inp_buf;
|
|
struct di_buf_s *di_post_inp_buf;
|
|
struct di_buf_s *di_inp_buf_next;
|
|
struct di_buf_s *di_mem_buf_dup_p;
|
|
struct di_buf_s *di_chan2_buf_dup_p;
|
|
/* pre output */
|
|
struct DI_SIM_MIF_s di_nrwr_mif;
|
|
struct DI_SIM_MIF_s di_mtnwr_mif;
|
|
struct di_buf_s *di_wr_buf;
|
|
struct di_buf_s *di_post_wr_buf;
|
|
struct DI_SIM_MIF_s di_contp2rd_mif;
|
|
struct DI_SIM_MIF_s di_contprd_mif;
|
|
struct DI_SIM_MIF_s di_contwr_mif;
|
|
int field_count_for_cont;
|
|
/*
|
|
* 0 (f0,null,f0)->nr0,
|
|
* 1 (f1,nr0,f1)->nr1_cnt,
|
|
* 2 (f2,nr1_cnt,nr0)->nr2_cnt
|
|
* 3 (f3,nr2_cnt,nr1_cnt)->nr3_cnt
|
|
*/
|
|
struct DI_MC_MIF_s di_mcinford_mif;
|
|
struct DI_MC_MIF_s di_mcvecwr_mif;
|
|
struct DI_MC_MIF_s di_mcinfowr_mif;
|
|
/* pre state */
|
|
int in_seq;
|
|
int recycle_seq;
|
|
int pre_ready_seq;
|
|
|
|
int pre_de_busy; /* 1 if pre_de is not done */
|
|
int pre_de_busy_timer_count;
|
|
int pre_de_process_done; /* flag when irq done */
|
|
int pre_de_process_flag; /* flag when pre_de_process done */
|
|
int pre_de_clear_flag;
|
|
/* flag is set when VFRAME_EVENT_PROVIDER_UNREG*/
|
|
int unreg_req_flag;
|
|
int unreg_req_flag_irq;
|
|
int unreg_req_flag_cnt;
|
|
int reg_req_flag;
|
|
/*int reg_req_flag_irq;*/
|
|
int reg_req_flag_cnt;
|
|
int reg_irq_busy;
|
|
int force_unreg_req_flag;
|
|
int disable_req_flag;
|
|
/* current source info */
|
|
int cur_width;
|
|
int cur_height;
|
|
int cur_inp_type;
|
|
int cur_source_type;
|
|
int cur_sig_fmt;
|
|
unsigned int orientation;
|
|
int cur_prog_flag; /* 1 for progressive source */
|
|
/* valid only when prog_proc_type is 0, for
|
|
* progressive source: top field 1, bot field 0
|
|
*/
|
|
int source_change_flag;
|
|
/* input size change flag, 1: need reconfig pre/nr/dnr size */
|
|
/* 0: not need config pre/nr/dnr size*/
|
|
bool input_size_change_flag;
|
|
/* true: bypass di all logic, false: not bypass */
|
|
bool bypass_flag;
|
|
unsigned char prog_proc_type;
|
|
/* set by prog_proc_config when source is vdin,0:use 2 i
|
|
* serial buffer,1:use 1 p buffer,3:use 2 i paralleling buffer
|
|
*/
|
|
unsigned char buf_alloc_mode;
|
|
/* alloc di buf as p or i;0: alloc buf as i;
|
|
* 1: alloc buf as p;
|
|
*/
|
|
unsigned char madi_enable;
|
|
unsigned char mcdi_enable;
|
|
unsigned int pps_dstw;
|
|
unsigned int pps_dsth;
|
|
int left_right;/*1,left eye; 0,right eye in field alternative*/
|
|
/*input2pre*/
|
|
int bypass_start_count;
|
|
/* need discard some vframe when input2pre => bypass */
|
|
unsigned char vdin2nr;
|
|
enum tvin_trans_fmt source_trans_fmt;
|
|
enum tvin_trans_fmt det3d_trans_fmt;
|
|
unsigned int det_lr;
|
|
unsigned int det_tp;
|
|
unsigned int det_la;
|
|
unsigned int det_null;
|
|
/*unsigned int width_bk;*/
|
|
#ifdef DET3D
|
|
int vframe_interleave_flag;
|
|
#endif
|
|
/**/
|
|
int pre_de_irq_timeout_count;
|
|
int pre_throw_flag;
|
|
int bad_frame_throw_count;
|
|
/*for static pic*/
|
|
int static_frame_count;
|
|
bool force_interlace;
|
|
bool by_pass_pre;
|
|
bool invert_flag;
|
|
bool vdin_source;
|
|
int nr_size;
|
|
int count_size;
|
|
int mcinfo_size;
|
|
int mv_size;
|
|
int mtn_size;
|
|
int cma_alloc_req;
|
|
int cma_alloc_done;
|
|
int cma_release_req;
|
|
/* for performance debug */
|
|
unsigned long irq_time[2];
|
|
/* combing adaptive */
|
|
struct combing_status_s *mtn_status;
|
|
u64 afbc_rls_time;
|
|
bool wait_afbc;
|
|
/*****************/
|
|
bool retry_en;
|
|
unsigned int retry_index;
|
|
unsigned int retry_cnt;
|
|
/*****************/
|
|
bool combing_fix_en;
|
|
unsigned int comb_mode;
|
|
/*struct di_patch_mov_s mov;*/
|
|
};
|
|
|
|
struct di_post_stru_s {
|
|
struct DI_MIF_s di_buf0_mif;
|
|
struct DI_MIF_s di_buf1_mif;
|
|
struct DI_MIF_s di_buf2_mif;
|
|
struct DI_SIM_MIF_s di_diwr_mif;
|
|
struct DI_SIM_MIF_s di_mtnprd_mif;
|
|
struct DI_MC_MIF_s di_mcvecrd_mif;
|
|
struct di_buf_s *cur_post_buf;
|
|
struct di_buf_s *keep_buf;
|
|
int update_post_reg_flag;
|
|
int run_early_proc_fun_flag;
|
|
int cur_disp_index;
|
|
int canvas_id;
|
|
int next_canvas_id;
|
|
bool toggle_flag;
|
|
bool vscale_skip_flag;
|
|
uint start_pts;
|
|
int buf_type;
|
|
int de_post_process_done;
|
|
int post_de_busy;
|
|
int di_post_num;
|
|
unsigned int post_peek_underflow;
|
|
unsigned int di_post_process_cnt;
|
|
unsigned int check_recycle_buf_cnt;
|
|
/* performance debug */
|
|
unsigned int post_wr_cnt;
|
|
unsigned long irq_time;
|
|
};
|
|
|
|
#define MAX_QUEUE_POOL_SIZE 256
|
|
struct queue_s {
|
|
unsigned int num;
|
|
unsigned int in_idx;
|
|
unsigned int out_idx;
|
|
unsigned int type; /* 0, first in first out;
|
|
* 1, general;2, fix position for di buf
|
|
*/
|
|
unsigned int pool[MAX_QUEUE_POOL_SIZE];
|
|
};
|
|
|
|
struct di_buf_pool_s {
|
|
struct di_buf_s *di_buf_ptr;
|
|
unsigned int size;
|
|
};
|
|
struct di_mm_s {
|
|
struct page *ppage;
|
|
unsigned long addr;
|
|
};
|
|
extern bool di_mm_alloc(int cma_mode, size_t count, struct di_mm_s *o);
|
|
extern bool di_mm_release(int cma_mode,
|
|
struct page *pages,
|
|
int count,
|
|
unsigned long addr);
|
|
|
|
|
|
unsigned char is_bypass(vframe_t *vf_in);
|
|
|
|
/*---get di state parameter---*/
|
|
struct di_dev_s *get_di_de_devp(void);
|
|
struct di_pre_stru_s *get_di_pre_stru(void);
|
|
struct di_post_stru_s *get_di_post_stru(void);
|
|
const char *get_di_version_s(void);
|
|
int get_di_dump_state_flag(void);
|
|
uint get_di_init_flag(void);
|
|
unsigned char get_di_recovery_flag(void);
|
|
unsigned int get_di_recovery_log_reason(void);
|
|
int get_di_di_blocking(void);
|
|
unsigned int get_di_recovery_log_queue_idx(void);
|
|
struct di_buf_s *get_di_recovery_log_di_buf(void);
|
|
int get_di_video_peek_cnt(void);
|
|
unsigned long get_di_reg_unreg_timeout_cnt(void);
|
|
struct vframe_s **get_di_vframe_in(void);
|
|
|
|
extern s32 di_request_afbc_hw(u8 id, bool on);
|
|
u32 di_request_afbc(u32 onoff);
|
|
unsigned int is_need_stop_reg(unsigned int addr);
|
|
/***********************/
|
|
extern bool di_wr_cue_int(void);
|
|
extern int reg_cue_int_show(struct seq_file *seq, void *v);
|
|
|
|
bool dil_attach_ext_api(const struct di_ext_ops *di_api);
|
|
/*--Different DI versions flag---*/
|
|
void dil_set_diff_ver_flag(unsigned int para);
|
|
|
|
unsigned int dil_get_diff_ver_flag(void);
|
|
/*-------------------------*/
|
|
struct di_buf_s *get_di_buf(int queue_idx, int *start_pos);
|
|
|
|
#define queue_for_each_entry(di_buf, ptm, queue_idx, list) \
|
|
for (itmp = 0; ((di_buf = get_di_buf(queue_idx, &itmp)) != NULL); )
|
|
|
|
#define di_dev_t struct di_dev_s
|
|
|
|
#define di_pr_info(fmt, args ...) pr_info("DI: " fmt, ## args)
|
|
|
|
#define pr_dbg(fmt, args ...) pr_debug("DI: " fmt, ## args)
|
|
|
|
#define pr_error(fmt, args ...) pr_err("DI: " fmt, ## args)
|
|
|
|
/******************************************/
|
|
/*#define DI_KEEP_HIS 0*/
|
|
#endif
|