blob: c71f4c80b27774370e502e2c9d29ea2deb247277 [file] [log] [blame]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* drivers/amlogic/media/deinterlace/deinterlace.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef _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/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_PROVERDER_UNREG 'n'
#define TRIGGER_PRE_BY_DEBUG_DISABLE 'd'
#define TRIGGER_PRE_BY_PROVERDER_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 4
/* 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 bypass_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_requeset_afbc(u32 onoff);
/***********************/
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_diffver_flag(unsigned int para);
unsigned int dil_get_diffver_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