mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
deinterlace: add di-multi folder v2 [2/3]
PD#SWPL-10064 Problem: add di-multi folder Solution: 1. add di_multi folder; 2. it can be enable by dts; 3. only one of di can be enabled at the same time; 4. no di-pq filse; Verify: U212 Change-Id: I8726d2430cf1beb58d0cd37c0358b7ea8e06c414 Signed-off-by: Jihong Sui <jihong.sui@amlogic.com>
This commit is contained in:
@@ -15104,3 +15104,7 @@ AMLOGIC DEINTERLACE DRIVER
|
||||
M: Jihong Sui <jihong.sui@amlogic.com>
|
||||
F: drivers/amlogic/media/deinterlace/di_pqa.h
|
||||
F: drivers/amlogic/media/di_local/*
|
||||
|
||||
AMLOGIC ADD DI_MULTI DRIVER
|
||||
M: Jihong Sui <jihong.sui@amlogic.com>
|
||||
F: drivers/amlogic/media/di_multi/*
|
||||
|
||||
@@ -89,6 +89,7 @@ source "drivers/amlogic/media/vout/Kconfig"
|
||||
source "drivers/amlogic/media/osd/Kconfig"
|
||||
source "drivers/amlogic/media/osd_ext/Kconfig"
|
||||
source "drivers/amlogic/media/deinterlace/Kconfig"
|
||||
source "drivers/amlogic/media/di_multi/Kconfig"
|
||||
source "drivers/amlogic/media/di_local/Kconfig"
|
||||
source "drivers/amlogic/media/vin/Kconfig"
|
||||
source "drivers/amlogic/media/video_processor/Kconfig"
|
||||
|
||||
@@ -5,6 +5,7 @@ obj-$(CONFIG_AMLOGIC_MEDIA_FB) += osd/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_FB_EXT) += osd_ext/
|
||||
obj-$(CONFIG_AMLOGIC_VOUT) += vout/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += deinterlace/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di_multi/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di_local/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_VIN) += vin/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_VIDEO_PROCESSOR) += video_processor/
|
||||
|
||||
15
drivers/amlogic/media/di_multi/Kconfig
Normal file
15
drivers/amlogic/media/di_multi/Kconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Deinterlace driver configuration
|
||||
#
|
||||
|
||||
menu "DI_MULTI driver"
|
||||
|
||||
config AMLOGIC_MEDIA_DEINTERLACE
|
||||
tristate "DI_MULTI driver"
|
||||
default n
|
||||
help
|
||||
Select to enable AMLOGIC DEINTERLACE driver
|
||||
process interlace source need three continueed fields,
|
||||
wave progressive source with two interlace fields from
|
||||
one progreesive fields
|
||||
endmenu
|
||||
34
drivers/amlogic/media/di_multi/Makefile
Normal file
34
drivers/amlogic/media/di_multi/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
# # Makefile for the Post Process Manager device #
|
||||
ifeq ($(TARGET_BUILD_VARIANT),userdebug)
|
||||
ccflags-y := -D DEBUG_SUPPORT
|
||||
ccflags-y := -DDEBUG
|
||||
else
|
||||
ccflags-y := -DDEBUG
|
||||
endif
|
||||
ccflags-y += -I.
|
||||
CFLAGS_dim.o := -I$(src)
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += dim.o
|
||||
dim-objs += deinterlace.o
|
||||
dim-objs += deinterlace_hw.o
|
||||
#dim-objs += deinterlace_mtn.o
|
||||
dim-objs += deinterlace_dbg.o
|
||||
#dim-objs += nr_drv.o
|
||||
#dim-objs += pulldown_drv.o
|
||||
#dim-objs += detect3d.o
|
||||
dim-objs += nr_downscale.o
|
||||
dim-objs += di_pps.o
|
||||
dim-objs += di_vframe.o
|
||||
dim-objs += di_prc.o
|
||||
dim-objs += di_pre.o
|
||||
dim-objs += di_post.o
|
||||
dim-objs += di_reg_tab.o
|
||||
dim-objs += di_dbg.o
|
||||
dim-objs += di_que.o
|
||||
dim-objs += di_sys.o
|
||||
dim-objs += di_task.o
|
||||
dim-objs += di_api.o
|
||||
#dim-objs += film_mode_fmw/vof_soft_top.o
|
||||
#dim-objs += film_mode_fmw/flm_mod_xx.o
|
||||
#dim-objs += film_mode_fmw/film_fw1.o
|
||||
ccflags-y += -Idrivers/amlogic/media/common/rdma/
|
||||
ccflags-y += -I$(src)
|
||||
8401
drivers/amlogic/media/di_multi/deinterlace.c
Normal file
8401
drivers/amlogic/media/di_multi/deinterlace.c
Normal file
File diff suppressed because it is too large
Load Diff
656
drivers/amlogic/media/di_multi/deinterlace.h
Normal file
656
drivers/amlogic/media/di_multi/deinterlace.h
Normal file
@@ -0,0 +1,656 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/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/vfm/vframe_provider.h>
|
||||
|
||||
#include "../di_local/di_local.h"
|
||||
#include <linux/clk.h>
|
||||
#include <linux/atomic.h>
|
||||
#include "deinterlace_hw.h"
|
||||
#include "../deinterlace/di_pqa.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 (4)
|
||||
#define MAX_LOCAL_BUF_NUM (7)
|
||||
#define MAX_POST_BUF_NUM (7) /*(5)*/ /* 16 */
|
||||
|
||||
#define VFRAME_TYPE_IN 1
|
||||
#define VFRAME_TYPE_LOCAL 2
|
||||
#define VFRAME_TYPE_POST 3
|
||||
#define VFRAME_TYPE_NUM 3
|
||||
|
||||
#define DI_POST_GET_LIMIT 4
|
||||
#define DI_PRE_READY_LIMIT 4
|
||||
/*vframe define*/
|
||||
#define vframe_t struct vframe_s
|
||||
|
||||
#define is_from_vdin(vframe) ((vframe)->type & VIDTYPE_VIU_422)
|
||||
|
||||
/* 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 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_height_mc; /*ary add for mc h is diff*/
|
||||
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*/
|
||||
/*0: n-2*/
|
||||
/*1: n-1*/
|
||||
/*2: n*/
|
||||
/*3: n+1*/
|
||||
/*4: n+2*/
|
||||
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;
|
||||
/*ary add */
|
||||
unsigned int channel;
|
||||
unsigned int width_bk; /*move from ppre*/
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
#if 0
|
||||
#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
|
||||
#else
|
||||
#define QUEUE_LOCAL_FREE 0
|
||||
#define QUEUE_RECYCLE 1 /* 5 */
|
||||
#define QUEUE_DISPLAY 2 /* 6 */
|
||||
#define QUEUE_TMP 3 /* 7 */
|
||||
#define QUEUE_POST_DOING 4 /* 8 */
|
||||
|
||||
#define QUEUE_IN_FREE 5 /* 1 */
|
||||
#define QUEUE_PRE_READY 6 /* 2 */
|
||||
#define QUEUE_POST_FREE 7 /* 3 */
|
||||
#define QUEUE_POST_READY 8 /* 4 QUE_POST_READY */
|
||||
|
||||
/*new use this for put back control*/
|
||||
#define QUEUE_POST_PUT_BACK (9)
|
||||
|
||||
#define QUEUE_NUM 5 /* 9 */
|
||||
#define QUEUE_NEW_THD_MIN (QUEUE_IN_FREE - 1)
|
||||
#define QUEUE_NEW_THD_MAX (QUEUE_POST_READY + 1)
|
||||
|
||||
#endif
|
||||
|
||||
#define queue_t struct queue_s
|
||||
|
||||
#define VFM_NAME "deinterlace"
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
|
||||
void enable_rdma(int enable_flag);
|
||||
int VSYNC_WR_MPEG_REG(u32 adr, u32 val);
|
||||
int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len);
|
||||
u32 VSYNC_RD_MPEG_REG(u32 adr);
|
||||
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
|
||||
|
||||
struct di_dev_s {
|
||||
dev_t devt;
|
||||
struct cdev cdev; /* The cdev structure */
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
dev_t devno;
|
||||
struct class *pclss;
|
||||
|
||||
bool sema_flg; /*di_sema_init_flag*/
|
||||
|
||||
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;
|
||||
bool mem_flg; /*ary add for make sure mem is ok*/
|
||||
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;
|
||||
unsigned int h_sc_down_en;/*sm1, tm2 ...*/
|
||||
/*struct mutex cma_mutex;*/
|
||||
unsigned int flag_cma;
|
||||
struct page *total_pages;
|
||||
struct dentry *dbg_root; /*dbg_fs*/
|
||||
/***************************/
|
||||
/*struct di_data_l_s data_l;*/
|
||||
void *data_l;
|
||||
|
||||
};
|
||||
|
||||
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;
|
||||
/* p_asi_next: ary:add for p */
|
||||
struct di_buf_s *p_asi_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_process_flag; /* flag when dim_pre_de_process done */
|
||||
int pre_de_clear_flag;
|
||||
/* flag is set when VFRAME_EVENT_PROVIDER_UNREG*/
|
||||
int unreg_req_flag_cnt;
|
||||
|
||||
int reg_req_flag_cnt;
|
||||
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
|
||||
*/
|
||||
/* ary: loacal play p mode is 0
|
||||
* local play i mode is 0
|
||||
*/
|
||||
|
||||
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; /*no use ?*/
|
||||
unsigned int pps_dsth; /*no use ?*/
|
||||
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_release_req;
|
||||
/* for performance debug */
|
||||
unsigned long irq_time[2];
|
||||
/* combing adaptive */
|
||||
struct combing_status_s *mtn_status;
|
||||
};
|
||||
|
||||
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;
|
||||
/*post doing buf and write buf to post ready*/
|
||||
struct di_buf_s *cur_post_buf;
|
||||
struct di_buf_s *keep_buf;
|
||||
struct di_buf_s *keep_buf_post; /*ary add for keep post 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;/*cp to di_hpre_s*/
|
||||
/* performance debug */
|
||||
unsigned int post_wr_cnt;
|
||||
unsigned long irq_time;
|
||||
|
||||
/*frame cnt*/
|
||||
unsigned int frame_cnt; /*cnt for post process*/
|
||||
};
|
||||
|
||||
#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 dim_mm_s {
|
||||
struct page *ppage;
|
||||
unsigned long addr;
|
||||
};
|
||||
|
||||
bool dim_mm_alloc(int cma_mode, size_t count, struct dim_mm_s *o);
|
||||
bool dim_mm_release(int cma_mode,
|
||||
struct page *pages,
|
||||
int count,
|
||||
unsigned long addr);
|
||||
|
||||
unsigned char dim_is_bypass(vframe_t *vf_in, unsigned int channel);
|
||||
bool dim_bypass_first_frame(unsigned int ch);
|
||||
|
||||
int di_cnt_buf(int width, int height, int prog_flag, int mc_mm,
|
||||
int bit10_support, int pack422);
|
||||
|
||||
/*---get di state parameter---*/
|
||||
struct di_dev_s *get_dim_de_devp(void);
|
||||
|
||||
const char *dim_get_version_s(void);
|
||||
int dim_get_dump_state_flag(void);
|
||||
|
||||
int dim_get_blocking(void);
|
||||
|
||||
struct di_buf_s *dim_get_recovery_log_di_buf(void);
|
||||
|
||||
unsigned long dim_get_reg_unreg_timeout_cnt(void);
|
||||
struct vframe_s **dim_get_vframe_in(unsigned int ch);
|
||||
int dim_check_recycle_buf(unsigned int channel);
|
||||
|
||||
int dim_seq_file_module_para_di(struct seq_file *seq);
|
||||
int dim_seq_file_module_para_hw(struct seq_file *seq);
|
||||
|
||||
int dim_seq_file_module_para_film_fw1(struct seq_file *seq);
|
||||
int dim_seq_file_module_para_mtn(struct seq_file *seq);
|
||||
|
||||
int dim_seq_file_module_para_pps(struct seq_file *seq);
|
||||
|
||||
int dim_seq_file_module_para_(struct seq_file *seq);
|
||||
|
||||
/***********************/
|
||||
|
||||
unsigned int di_get_dts_nrds_en(void);
|
||||
int di_get_disp_cnt(void);
|
||||
|
||||
/*---------------------*/
|
||||
long dim_pq_load_io(unsigned long arg);
|
||||
int dim_get_canvas(void);
|
||||
unsigned int dim_cma_alloc_total(struct di_dev_s *de_devp);
|
||||
irqreturn_t dim_irq(int irq, void *dev_instance);
|
||||
irqreturn_t dim_post_irq(int irq, void *dev_instance);
|
||||
|
||||
void dim_rdma_init(void);
|
||||
void dim_rdma_exit(void);
|
||||
|
||||
void dim_set_di_flag(void);
|
||||
void dim_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev);
|
||||
|
||||
void dim_log_buffer_state(unsigned char *tag, unsigned int channel);
|
||||
|
||||
unsigned char dim_pre_de_buf_config(unsigned int channel);
|
||||
void dim_pre_de_process(unsigned int channel);
|
||||
void dim_pre_de_done_buf_config(unsigned int channel, bool flg_timeout);
|
||||
void dim_pre_de_done_buf_clear(unsigned int channel);
|
||||
|
||||
void di_reg_setting(unsigned int channel, struct vframe_s *vframe);
|
||||
void di_reg_variable(unsigned int channel, struct vframe_s *vframe);
|
||||
|
||||
void dim_unreg_process_irq(unsigned int channel);
|
||||
void di_unreg_variable(unsigned int channel);
|
||||
void di_unreg_setting(void);
|
||||
|
||||
void dim_uninit_buf(unsigned int disable_mirror, unsigned int channel);
|
||||
void dim_unreg_process(unsigned int channel);
|
||||
|
||||
int dim_process_post_vframe(unsigned int channel);
|
||||
unsigned char dim_check_di_buf(struct di_buf_s *di_buf, int reason,
|
||||
unsigned int channel);
|
||||
int dim_do_post_wr_fun(void *arg, vframe_t *disp_vf);
|
||||
int dim_post_process(void *arg, unsigned int zoom_start_x_lines,
|
||||
unsigned int zoom_end_x_lines,
|
||||
unsigned int zoom_start_y_lines,
|
||||
unsigned int zoom_end_y_lines, vframe_t *disp_vf);
|
||||
void dim_post_de_done_buf_config(unsigned int channel);
|
||||
void dim_recycle_post_back(unsigned int channel);
|
||||
void recycle_post_ready_local(struct di_buf_s *di_buf,
|
||||
unsigned int channel);
|
||||
|
||||
/*--------------------------*/
|
||||
unsigned char dim_vcry_get_flg(void);
|
||||
void dim_vcry_flg_inc(void);
|
||||
void dim_vcry_set_flg(unsigned char val);
|
||||
/*--------------------------*/
|
||||
unsigned int dim_vcry_get_log_reason(void);
|
||||
void dim_vcry_set_log_reason(unsigned int val);
|
||||
/*--------------------------*/
|
||||
unsigned char dim_vcry_get_log_q_idx(void);
|
||||
void dim_vcry_set_log_q_idx(unsigned int val);
|
||||
/*--------------------------*/
|
||||
struct di_buf_s **dim_vcry_get_log_di_buf(void);
|
||||
void dim_vcry_set_log_di_buf(struct di_buf_s *di_bufp);
|
||||
void dim_vcry_set(unsigned int reason, unsigned int idx,
|
||||
struct di_buf_s *di_bufp);
|
||||
|
||||
const char *dim_get_vfm_type_name(unsigned int nub);
|
||||
|
||||
bool dim_cma_top_alloc(unsigned int ch);
|
||||
bool dim_cma_top_release(unsigned int ch);
|
||||
|
||||
int dim_get_reg_unreg_cnt(void);
|
||||
void dim_reg_timeout_inc(void);
|
||||
|
||||
void dim_reg_process(unsigned int channel);
|
||||
bool is_bypass2(struct vframe_s *vf_in, unsigned int ch);
|
||||
|
||||
/*--------------------------*/
|
||||
int di_ori_event_unreg(unsigned int channel);
|
||||
int di_ori_event_reg(void *data, unsigned int channel);
|
||||
int di_ori_event_qurey_vdin2nr(unsigned int channel);
|
||||
int di_ori_event_reset(unsigned int channel);
|
||||
int di_ori_event_light_unreg(unsigned int channel);
|
||||
int di_ori_event_light_unreg_revframe(unsigned int channel);
|
||||
int di_ori_event_ready(unsigned int channel);
|
||||
int di_ori_event_qurey_state(unsigned int channel);
|
||||
void di_ori_event_set_3D(int type, void *data, unsigned int channel);
|
||||
|
||||
/*--------------------------*/
|
||||
extern int pre_run_flag;
|
||||
extern unsigned int dbg_first_cnt_pre;
|
||||
extern spinlock_t plist_lock;
|
||||
|
||||
void dim_dbg_pre_cnt(unsigned int channel, char *item);
|
||||
|
||||
void diext_clk_b_sw(bool on);
|
||||
|
||||
int di_vf_l_states(struct vframe_states *states, unsigned int channel);
|
||||
struct vframe_s *di_vf_l_peek(unsigned int channel);
|
||||
void di_vf_l_put(struct vframe_s *vf, unsigned char channel);
|
||||
struct vframe_s *di_vf_l_get(unsigned int channel);
|
||||
|
||||
unsigned char pre_p_asi_de_buf_config(unsigned int ch);
|
||||
|
||||
/*---------------------*/
|
||||
|
||||
ssize_t
|
||||
store_config(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t
|
||||
store_dbg(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t
|
||||
store_dump_mem(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len);
|
||||
ssize_t
|
||||
store_log(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t
|
||||
show_vframe_status(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf);
|
||||
|
||||
ssize_t dim_read_log(char *buf);
|
||||
|
||||
/*---------------------*/
|
||||
|
||||
struct di_buf_s *dim_get_buf(unsigned int channel,
|
||||
int queue_idx, int *start_pos);
|
||||
|
||||
#define queue_for_each_entry(di_buf, channel, queue_idx, list) \
|
||||
for (itmp = 0; \
|
||||
((di_buf = dim_get_buf(channel, 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)
|
||||
|
||||
/*this is debug for buf*/
|
||||
/*#define DI_DEBUG_POST_BUF_FLOW (1)*/
|
||||
|
||||
#endif
|
||||
1214
drivers/amlogic/media/di_multi/deinterlace_dbg.c
Normal file
1214
drivers/amlogic/media/di_multi/deinterlace_dbg.c
Normal file
File diff suppressed because it is too large
Load Diff
43
drivers/amlogic/media/di_multi/deinterlace_dbg.h
Normal file
43
drivers/amlogic/media/di_multi/deinterlace_dbg.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/deinterlace_dbg.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_DBG_H
|
||||
#define _DI_DBG_H
|
||||
#include "deinterlace.h"
|
||||
|
||||
void dim_parse_cmd_params(char *buf_orig, char **parm);
|
||||
void dim_dump_pre_stru(struct di_pre_stru_s *ppre);
|
||||
void dim_dump_post_stru(struct di_post_stru_s *di_post_stru_p);
|
||||
void dim_dump_di_buf(struct di_buf_s *di_buf);
|
||||
void dim_dump_pool(struct queue_s *q);
|
||||
void dim_dump_vframe(vframe_t *vf);
|
||||
void dim_print_di_buf(struct di_buf_s *di_buf, int format);
|
||||
void dim_dump_pre_mif_state(void);
|
||||
void dim_dump_post_mif_reg(void);
|
||||
void dim_dump_buf_addr(struct di_buf_s *di_buf, unsigned int num);
|
||||
void dim_dump_mif_size_state(struct di_pre_stru_s *pre,
|
||||
struct di_post_stru_s *post);
|
||||
void debug_device_files_add(struct device *dev);
|
||||
void debug_device_files_del(struct device *dev);
|
||||
void dim_debugfs_init(void);
|
||||
void dim_debugfs_exit(void);
|
||||
int dim_state_show(struct seq_file *seq, void *v,
|
||||
unsigned int channel);
|
||||
int dim_dump_mif_size_state_show(struct seq_file *seq, void *v,
|
||||
unsigned int channel);
|
||||
|
||||
#endif
|
||||
4236
drivers/amlogic/media/di_multi/deinterlace_hw.c
Normal file
4236
drivers/amlogic/media/di_multi/deinterlace_hw.c
Normal file
File diff suppressed because it is too large
Load Diff
277
drivers/amlogic/media/di_multi/deinterlace_hw.h
Normal file
277
drivers/amlogic/media/di_multi/deinterlace_hw.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/deinterlace_hw.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_HW_H
|
||||
#define _DI_HW_H
|
||||
#include <linux/amlogic/media/amvecm/amvecm.h>
|
||||
|
||||
#include "../deinterlace/di_pqa.h"
|
||||
|
||||
/* if post size < 80, filter of ei can't work */
|
||||
#define MIN_POST_WIDTH 80
|
||||
#define MIN_BLEND_WIDTH 27
|
||||
|
||||
#define SKIP_CTRE_NUM 13
|
||||
/*move from deinterlace.c*/
|
||||
enum eAFBC_REG {
|
||||
eAFBC_ENABLE,
|
||||
eAFBC_MODE,
|
||||
eAFBC_SIZE_IN,
|
||||
eAFBC_DEC_DEF_COLOR,
|
||||
eAFBC_CONV_CTRL,
|
||||
eAFBC_LBUF_DEPTH,
|
||||
eAFBC_HEAD_BADDR,
|
||||
eAFBC_BODY_BADDR,
|
||||
eAFBC_SIZE_OUT,
|
||||
eAFBC_OUT_YSCOPE,
|
||||
eAFBC_STAT,
|
||||
eAFBC_VD_CFMT_CTRL,
|
||||
eAFBC_VD_CFMT_W,
|
||||
eAFBC_MIF_HOR_SCOPE,
|
||||
eAFBC_MIF_VER_SCOPE,
|
||||
eAFBC_PIXEL_HOR_SCOPE,
|
||||
eAFBC_PIXEL_VER_SCOPE,
|
||||
eAFBC_VD_CFMT_H,
|
||||
};
|
||||
|
||||
enum eAFBC_DEC {
|
||||
eAFBC_DEC0,
|
||||
eAFBC_DEC1,
|
||||
};
|
||||
|
||||
#define AFBC_REG_INDEX_NUB (18)
|
||||
#define AFBC_DEC_NUB (2)
|
||||
|
||||
struct DI_MIF_s {
|
||||
unsigned short luma_x_start0;
|
||||
unsigned short luma_x_end0;
|
||||
unsigned short luma_y_start0;
|
||||
unsigned short luma_y_end0;
|
||||
unsigned short chroma_x_start0;
|
||||
unsigned short chroma_x_end0;
|
||||
unsigned short chroma_y_start0;
|
||||
unsigned short chroma_y_end0;
|
||||
unsigned int nocompress;
|
||||
unsigned set_separate_en:2;
|
||||
unsigned src_field_mode:1;
|
||||
unsigned src_prog:1;
|
||||
unsigned video_mode:1;
|
||||
unsigned output_field_num:1;
|
||||
unsigned bit_mode:2;
|
||||
/*
|
||||
* unsigned burst_size_y:2; set 3 as default
|
||||
* unsigned burst_size_cb:2;set 1 as default
|
||||
* unsigned burst_size_cr:2;set 1 as default
|
||||
*/
|
||||
unsigned canvas0_addr0:8;
|
||||
unsigned canvas0_addr1:8;
|
||||
unsigned canvas0_addr2:8;
|
||||
};
|
||||
|
||||
struct DI_SIM_MIF_s {
|
||||
unsigned short start_x;
|
||||
unsigned short end_x;
|
||||
unsigned short start_y;
|
||||
unsigned short end_y;
|
||||
unsigned short canvas_num;
|
||||
unsigned short bit_mode;
|
||||
};
|
||||
|
||||
struct DI_MC_MIF_s {
|
||||
unsigned short start_x;
|
||||
unsigned short start_y;
|
||||
unsigned short end_y;
|
||||
unsigned short size_x;
|
||||
unsigned short size_y;
|
||||
unsigned short canvas_num;
|
||||
unsigned short blend_en;
|
||||
unsigned short vecrd_offset;
|
||||
};
|
||||
|
||||
enum gate_mode_e {
|
||||
GATE_AUTO,
|
||||
GATE_ON,
|
||||
GATE_OFF,
|
||||
};
|
||||
|
||||
struct mcinfo_lmv_s {
|
||||
unsigned char lock_flag;
|
||||
char lmv;
|
||||
unsigned short lock_cnt;
|
||||
};
|
||||
|
||||
struct di_pq_parm_s {
|
||||
struct am_pq_parm_s pq_parm;
|
||||
struct am_reg_s *regs;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void dim_read_pulldown_info(unsigned int *glb_frm_mot_num,
|
||||
unsigned int *glb_fid_mot_num);
|
||||
|
||||
#if 0
|
||||
|
||||
void read_new_pulldown_info(struct FlmModReg_t *pFMRegp);
|
||||
#endif
|
||||
void dim_pulldown_info_clear_g12a(void);
|
||||
void dimh_combing_pd22_window_config(unsigned int width, unsigned int height);
|
||||
void dimh_hw_init(bool pulldown_en, bool mc_enable);
|
||||
void dimh_hw_uninit(void);
|
||||
void dimh_enable_di_pre_aml(struct DI_MIF_s *di_inp_mif,
|
||||
struct DI_MIF_s *di_mem_mif,
|
||||
struct DI_MIF_s *di_chan2_mif,
|
||||
struct DI_SIM_MIF_s *di_nrwr_mif,
|
||||
struct DI_SIM_MIF_s *di_mtnwr_mif,
|
||||
struct DI_SIM_MIF_s *di_contp2rd_mif,
|
||||
struct DI_SIM_MIF_s *di_contprd_mif,
|
||||
struct DI_SIM_MIF_s *di_contwr_mif,
|
||||
unsigned char madi_en,
|
||||
unsigned char pre_field_num,
|
||||
unsigned char pre_vdin_link);
|
||||
void dimh_enable_afbc_input(struct vframe_s *vf);
|
||||
|
||||
void dimh_mc_pre_mv_irq(void);
|
||||
void dimh_enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif,
|
||||
struct DI_MC_MIF_s *di_mcinfowr_mif,
|
||||
struct DI_MC_MIF_s *di_mcvecwr_mif,
|
||||
unsigned char mcdi_en);
|
||||
void dimh_enable_mc_di_pre_g12(struct DI_MC_MIF_s *di_mcinford_mif,
|
||||
struct DI_MC_MIF_s *di_mcinfowr_mif,
|
||||
struct DI_MC_MIF_s *di_mcvecwr_mif,
|
||||
unsigned char mcdi_en);
|
||||
|
||||
void dimh_enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif,
|
||||
int urgent, bool reverse, int invert_mv);
|
||||
void dimh_enable_mc_di_post_g12(struct DI_MC_MIF_s *di_mcvecrd_mif,
|
||||
int urgent, bool reverse, int invert_mv);
|
||||
|
||||
void dimh_disable_post_deinterlace_2(void);
|
||||
void dimh_initial_di_post_2(int hsize_post, int vsize_post,
|
||||
int hold_line, bool write_en);
|
||||
void dimh_enable_di_post_2(
|
||||
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,
|
||||
int ei_en, int blend_en, int blend_mtn_en, int blend_mode,
|
||||
int di_vpp_en, int di_ddr_en,
|
||||
int post_field_num, int hold_line, int urgent,
|
||||
int invert_mv, int vskip_cnt
|
||||
);
|
||||
void dimh_post_switch_buffer(
|
||||
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,
|
||||
int ei_en, int blend_en, int blend_mtn_en, int blend_mode,
|
||||
int di_vpp_en, int di_ddr_en,
|
||||
int post_field_num, int hold_line, int urgent,
|
||||
int invert_mv, bool pd_en, bool mc_enable,
|
||||
int vskip_cnt
|
||||
);
|
||||
void dim_post_read_reverse_irq(bool reverse,
|
||||
unsigned char mc_pre_flag, bool mc_enable);
|
||||
void dim_top_gate_control(bool top_en, bool mc_en);
|
||||
void dim_pre_gate_control(bool enable, bool mc_enable);
|
||||
void dim_post_gate_control(bool gate);
|
||||
void dim_set_power_control(unsigned char enable);
|
||||
void dim_hw_disable(bool mc_enable);
|
||||
void dimh_enable_di_pre_mif(bool enable, bool mc_enable);
|
||||
void dimh_enable_di_post_mif(enum gate_mode_e mode);
|
||||
|
||||
void dimh_combing_pd22_window_config(unsigned int width, unsigned int height);
|
||||
void dimh_calc_lmv_init(void);
|
||||
void dimh_calc_lmv_base_mcinfo(unsigned int vf_height,
|
||||
unsigned long mcinfo_adr,
|
||||
unsigned int mcinfo_size);
|
||||
void dimh_init_field_mode(unsigned short height);
|
||||
void dim_film_mode_win_config(unsigned int width, unsigned int height);
|
||||
void dimh_pulldown_vof_win_config(struct pulldown_detected_s *wins);
|
||||
void dimh_load_regs(struct di_pq_parm_s *di_pq_ptr);
|
||||
void dim_pre_frame_reset_g12(unsigned char madi_en, unsigned char mcdi_en);
|
||||
void dim_pre_frame_reset(void);
|
||||
void dimh_interrupt_ctrl(unsigned char ma_en,
|
||||
unsigned char det3d_en, unsigned char nrds_en,
|
||||
unsigned char post_wr, unsigned char mc_en);
|
||||
void dimh_txl_patch_prog(int prog_flg, unsigned int cnt, bool mc_en);
|
||||
bool dimh_afbc_is_supported(void);
|
||||
|
||||
void dimh_afbc_reg_sw(bool on);
|
||||
|
||||
void dump_vd2_afbc(void);
|
||||
|
||||
u8 *dim_vmap(ulong addr, u32 size, bool *bflg);
|
||||
void dim_unmap_phyaddr(u8 *vaddr);
|
||||
int dim_print(const char *fmt, ...);
|
||||
|
||||
#define DI_MC_SW_OTHER (1 << 0)
|
||||
#define DI_MC_SW_REG (1 << 1)
|
||||
/*#define DI_MC_SW_POST (1 << 2)*/
|
||||
#define DI_MC_SW_IC (1 << 2)
|
||||
|
||||
#define DI_MC_SW_ON_MASK (DI_MC_SW_REG | DI_MC_SW_OTHER | DI_MC_SW_IC)
|
||||
|
||||
void dimh_patch_post_update_mc(void);
|
||||
void dimh_patch_post_update_mc_sw(unsigned int cmd, bool on);
|
||||
|
||||
void dim_rst_protect(bool on);
|
||||
void dim_pre_nr_wr_done_sel(bool on);
|
||||
void dim_arb_sw(bool on);
|
||||
void dbg_set_DI_PRE_CTRL(void);
|
||||
void di_async_reset2(void); /*2019-04-05 add for debug*/
|
||||
|
||||
enum DI_HW_POST_CTRL {
|
||||
DI_HW_POST_CTRL_INIT,
|
||||
DI_HW_POST_CTRL_RESET,
|
||||
};
|
||||
|
||||
void dimh_post_ctrl(enum DI_HW_POST_CTRL contr,
|
||||
unsigned int post_write_en);
|
||||
void dimh_int_ctr(unsigned int set_mod, unsigned char ma_en,
|
||||
unsigned char det3d_en, unsigned char nrds_en,
|
||||
unsigned char post_wr, unsigned char mc_en);
|
||||
|
||||
void h_dbg_reg_set(unsigned int val);
|
||||
|
||||
enum eDI_POST_FLOW {
|
||||
eDI_POST_FLOW_STEP1_STOP,
|
||||
eDI_POST_FLOW_STEP2_START,
|
||||
/* eDI_POST_FLOW_STEP3_RESET_INT,*/
|
||||
};
|
||||
|
||||
void di_post_set_flow(unsigned int post_wr_en, enum eDI_POST_FLOW step);
|
||||
void post_mif_sw(bool on);
|
||||
void post_dbg_contr(void);
|
||||
void post_close_new(void);
|
||||
void di_post_reset(void);
|
||||
void dimh_pst_trig_resize(void);
|
||||
|
||||
void hpst_power_ctr(bool on);
|
||||
void hpst_dbg_power_ctr_trig(unsigned int cmd);
|
||||
void hpst_dbg_mem_pd_trig(unsigned int cmd);
|
||||
void hpst_dbg_trig_gate(unsigned int cmd);
|
||||
void hpst_dbg_trig_mif(unsigned int cmd);
|
||||
void hpst_mem_pd_sw(unsigned int on);
|
||||
void hpst_vd1_sw(unsigned int on);
|
||||
|
||||
void dim_init_setting_once(void);
|
||||
void dim_hw_init_reg(void);
|
||||
|
||||
#endif
|
||||
106
drivers/amlogic/media/di_multi/di_api.c
Normal file
106
drivers/amlogic/media/di_multi/di_api.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_api.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/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/amlogic/media/vpu/vpu.h>
|
||||
|
||||
#include "di_api.h"
|
||||
/**********************************
|
||||
* DI api is used for other module
|
||||
*********************************/
|
||||
static const struct di_ext_ops di_ext = {
|
||||
.di_post_reg_rd = l_DI_POST_REG_RD,
|
||||
.di_post_wr_reg_bits = l_DI_POST_WR_REG_BITS,
|
||||
};
|
||||
|
||||
void dim_attach_to_local(void)
|
||||
{
|
||||
dil_attach_ext_api(&di_ext);
|
||||
}
|
||||
|
||||
bool dim_attach_ext_api(struct di_ext_ops *di_api)
|
||||
{
|
||||
#if 1
|
||||
if (!di_api)
|
||||
return false;
|
||||
|
||||
memcpy(di_api, &di_ext, sizeof(struct di_ext_ops));
|
||||
#else
|
||||
di_api = &di_ext;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*EXPORT_SYMBOL(dim_attach_ext_api);*/
|
||||
|
||||
/**********************************
|
||||
* ext_api used by DI
|
||||
********************************/
|
||||
#define ARY_TEMP2
|
||||
#ifdef ARY_TEMP2
|
||||
void ext_switch_vpu_mem_pd_vmod(unsigned int vmod, bool on)
|
||||
{
|
||||
switch_vpu_mem_pd_vmod(vmod,
|
||||
on ? VPU_MEM_POWER_ON : VPU_MEM_POWER_DOWN);
|
||||
}
|
||||
|
||||
const struct ext_ops_s ext_ops = {
|
||||
.switch_vpu_mem_pd_vmod = ext_switch_vpu_mem_pd_vmod,
|
||||
/*no use ?*/
|
||||
/* .vf_get_receiver_name = vf_get_receiver_name,*/
|
||||
.switch_vpu_clk_gate_vmod = switch_vpu_clk_gate_vmod,
|
||||
.get_current_vscale_skip_count = get_current_vscale_skip_count,
|
||||
.canvas_pool_alloc_canvas_table = canvas_pool_alloc_canvas_table,
|
||||
};
|
||||
|
||||
#else
|
||||
void n_switch_vpu_mem_pd_vmod(unsigned int vmod, bool on)
|
||||
{
|
||||
}
|
||||
|
||||
char *n_vf_get_receiver_name(const char *provider_name)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void n_switch_vpu_clk_gate_vmod(unsigned int vmod, int flag)
|
||||
{
|
||||
}
|
||||
|
||||
int n_get_current_vscale_skip_count(struct vframe_s *vf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 n_canvas_pool_alloc_canvas_table(const char *owner, u32 *tab,
|
||||
int size,
|
||||
enum canvas_map_type_e type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ext_ops_s ext_ops = {
|
||||
.switch_vpu_mem_pd_vmod = n_switch_vpu_mem_pd_vmod,
|
||||
.vf_get_receiver_name = n_vf_get_receiver_name,
|
||||
.switch_vpu_clk_gate_vmod = n_switch_vpu_clk_gate_vmod,
|
||||
.get_current_vscale_skip_count = n_get_current_vscale_skip_count,
|
||||
.canvas_pool_alloc_canvas_table = n_canvas_pool_alloc_canvas_table,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
55
drivers/amlogic/media/di_multi/di_api.h
Normal file
55
drivers/amlogic/media/di_multi/di_api.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_api.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_API_H__
|
||||
#define __DI_API_H__
|
||||
|
||||
#include <linux/amlogic/media/canvas/canvas_mgr.h>
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "../di_local/di_local.h"
|
||||
|
||||
/*--------------------------*/
|
||||
unsigned int l_DI_POST_REG_RD(unsigned int addr);
|
||||
int l_DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len);
|
||||
|
||||
/*--------------------------*/
|
||||
bool di_attach_ext_api(struct di_ext_ops *di_api);
|
||||
|
||||
/*attach di_ops to di_local*/
|
||||
bool dil_attach_ext_api(const struct di_ext_ops *di_api);
|
||||
void dim_attach_to_local(void);
|
||||
|
||||
/*--------------------------*/
|
||||
int get_current_vscale_skip_count(struct vframe_s *vf);
|
||||
|
||||
struct ext_ops_s {
|
||||
void (*switch_vpu_mem_pd_vmod)(unsigned int vmod, bool on);
|
||||
/* char *(*vf_get_receiver_name)(const char *provider_name);*/
|
||||
void (*switch_vpu_clk_gate_vmod)(unsigned int vmod, int flag);
|
||||
int (*get_current_vscale_skip_count)(struct vframe_s *vf);
|
||||
u32 (*canvas_pool_alloc_canvas_table)(const char *owner, u32 *tab,
|
||||
int size,
|
||||
enum canvas_map_type_e type);
|
||||
};
|
||||
|
||||
extern const struct ext_ops_s ext_ops;
|
||||
|
||||
/*--------------------------*/
|
||||
void dil_get_rev_mem(unsigned long *mstart, unsigned int *msize);
|
||||
void dil_get_flg(unsigned int *flg);
|
||||
|
||||
#endif /*__DI_API_H__*/
|
||||
21
drivers/amlogic/media/di_multi/di_data.h
Normal file
21
drivers/amlogic/media/di_multi/di_data.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_data.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_DATA_H__
|
||||
#define __DI_DATA_H__
|
||||
|
||||
#endif /*__DI_DATA_H__*/
|
||||
1372
drivers/amlogic/media/di_multi/di_data_l.h
Normal file
1372
drivers/amlogic/media/di_multi/di_data_l.h
Normal file
File diff suppressed because it is too large
Load Diff
1632
drivers/amlogic/media/di_multi/di_dbg.c
Normal file
1632
drivers/amlogic/media/di_multi/di_dbg.c
Normal file
File diff suppressed because it is too large
Load Diff
69
drivers/amlogic/media/di_multi/di_dbg.h
Normal file
69
drivers/amlogic/media/di_multi/di_dbg.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_dbg.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_DBG_H__
|
||||
#define __DI_DBG_H__
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_provider.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_receiver.h>
|
||||
|
||||
void didbg_fs_init(void);
|
||||
void didbg_fs_exit(void);
|
||||
|
||||
void di_cfgx_init_val(void);
|
||||
|
||||
void didbg_vframe_in_copy(unsigned int ch, struct vframe_s *pvfm);
|
||||
void didbg_vframe_out_save(struct vframe_s *pvfm);
|
||||
|
||||
/********************************
|
||||
*debug register:
|
||||
*******************************/
|
||||
void ddbg_reg_save(unsigned int addr, unsigned int val,
|
||||
unsigned int st, unsigned int bw);
|
||||
void dim_ddbg_mod_save(unsigned int mod,
|
||||
unsigned int ch,
|
||||
unsigned int cnt);
|
||||
void ddbg_sw(unsigned int mode, bool on);
|
||||
|
||||
/********************************
|
||||
*time:
|
||||
*******************************/
|
||||
u64 cur_to_msecs(void);
|
||||
u64 cur_to_usecs(void); /*2019*/
|
||||
|
||||
/********************************
|
||||
*trace:
|
||||
*******************************/
|
||||
struct dim_tr_ops_s {
|
||||
void (*pre)(unsigned int index, unsigned long ctime);
|
||||
void (*post)(unsigned int index, unsigned long ctime);
|
||||
void (*pre_get)(unsigned int index);
|
||||
void (*pre_set)(unsigned int index);
|
||||
void (*pre_ready)(unsigned int index);
|
||||
void (*post_ready)(unsigned int index);
|
||||
void (*post_get)(unsigned int index);
|
||||
void (*post_get2)(unsigned int index);
|
||||
void (*post_set)(unsigned int index);
|
||||
void (*post_ir)(unsigned int index);
|
||||
void (*post_do)(unsigned int index);
|
||||
void (*post_peek)(unsigned int index);
|
||||
};
|
||||
|
||||
extern const struct dim_tr_ops_s dim_tr_ops;
|
||||
|
||||
#endif /*__DI_DBG_H__*/
|
||||
389
drivers/amlogic/media/di_multi/di_post.c
Normal file
389
drivers/amlogic/media/di_multi/di_post.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_post.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "deinterlace.h"
|
||||
#include "deinterlace_dbg.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_data.h"
|
||||
#include "di_dbg.h"
|
||||
#include "di_vframe.h"
|
||||
#include "di_que.h"
|
||||
#include "di_task.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
#include "di_post.h"
|
||||
|
||||
#include "nr_downscale.h"
|
||||
#include "register.h"
|
||||
|
||||
void dpost_clear(void)/*not been called*/
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
memset(pst, 0, sizeof(struct di_hpst_s));
|
||||
}
|
||||
|
||||
void dpost_init(void)
|
||||
{/*reg:*/
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
|
||||
/*timer out*/
|
||||
di_tout_int(&pst->tout, 40); /*ms*/
|
||||
}
|
||||
|
||||
void pw_use_hw_post(enum eDI_SUB_ID channel, bool on)
|
||||
{
|
||||
struct di_hpst_s *post = get_hw_pst();
|
||||
|
||||
post->hw_flg_busy_post = on;
|
||||
if (on)
|
||||
post->curr_ch = channel;
|
||||
}
|
||||
|
||||
static bool pw_try_sw_ch_next_post(enum eDI_SUB_ID channel)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
struct di_hpst_s *post = get_hw_pst();
|
||||
enum eDI_SUB_ID lst_ch, nch;
|
||||
|
||||
lst_ch = channel;
|
||||
|
||||
nch = pw_ch_next_count(lst_ch);
|
||||
if (!get_reg_flag(nch) || get_flag_trig_unreg(nch))
|
||||
return false;
|
||||
|
||||
if (nch != channel)
|
||||
dim_ddbg_mod_save(eDI_DBG_MOD_POST_CH_CHG, nch, 0);/*dbg*/
|
||||
|
||||
post->curr_ch = nch;
|
||||
post->hw_flg_busy_post = true;
|
||||
ret = true;
|
||||
|
||||
/*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* debug */
|
||||
/*****************************/
|
||||
|
||||
/*****************************/
|
||||
/* STEP */
|
||||
/*****************************/
|
||||
|
||||
bool dpst_step_idle(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
bool reflesh = false;
|
||||
|
||||
if (!pw_try_sw_ch_next_post(pst->curr_ch))
|
||||
return false;
|
||||
|
||||
pst->pres = get_pre_stru(pst->curr_ch);
|
||||
pst->psts = get_post_stru(pst->curr_ch);
|
||||
pst->state++;/*tmp*/
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_check(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
struct di_post_stru_s *ppost;
|
||||
bool reflesh = false;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
ppost = get_post_stru(ch);
|
||||
|
||||
if (queue_empty(ch, QUEUE_POST_DOING)) {
|
||||
ppost->post_peek_underflow++;
|
||||
pst->state--;
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
pst->state++;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_set(void)
|
||||
{
|
||||
struct di_buf_s *di_buf = NULL;
|
||||
vframe_t *vf_p = NULL;
|
||||
struct di_post_stru_s *ppost;
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
bool reflesh = false;
|
||||
ulong flags = 0;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
ppost = get_post_stru(ch);
|
||||
|
||||
di_buf = get_di_buf_head(ch, QUEUE_POST_DOING);
|
||||
if (dim_check_di_buf(di_buf, 20, ch)) {
|
||||
PR_ERR("%s:err1\n", __func__);
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
vf_p = di_buf->vframe;
|
||||
if (ppost->run_early_proc_fun_flag) {
|
||||
if (vf_p->early_process_fun)
|
||||
vf_p->early_process_fun = dim_do_post_wr_fun;
|
||||
}
|
||||
|
||||
dim_print("%s:pr_index=%d\n", __func__, di_buf->process_fun_index);
|
||||
if (di_buf->process_fun_index) { /*not bypass?*/
|
||||
|
||||
ppost->post_wr_cnt++;
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_post_process(di_buf, 0, vf_p->width - 1,
|
||||
0, vf_p->height - 1, vf_p);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
|
||||
/*begin to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_EN, &pst->tout);
|
||||
|
||||
ppost->post_de_busy = 1;
|
||||
ppost->irq_time = cur_to_msecs();
|
||||
|
||||
/*state*/
|
||||
pst->state++;
|
||||
/*reflesh = true;*/
|
||||
} else {
|
||||
ppost->de_post_process_done = 1; /*trig done*/
|
||||
pst->flg_int_done = 1;
|
||||
|
||||
/*state*/
|
||||
pst->state++;/*pst->state = eDI_PST_ST_DONE;*/
|
||||
reflesh = true;
|
||||
}
|
||||
ppost->cur_post_buf = di_buf;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_wait_int(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
struct di_post_stru_s *ppost;
|
||||
bool reflesh = false;
|
||||
ulong flags = 0;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
|
||||
dim_print("%s:ch[%d],done_flg[%d]\n", __func__,
|
||||
pst->curr_ch, pst->flg_int_done);
|
||||
if (pst->flg_int_done) {
|
||||
/*finish to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_FINISH, &pst->tout);
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_post_de_done_buf_config(ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
pst->flg_int_done = false;
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
reflesh = true;
|
||||
} else {
|
||||
/*check if timeout:*/
|
||||
if (di_tout_contr(eDI_TOUT_CONTR_CHECK, &pst->tout)) {
|
||||
ppost = get_post_stru(ch);
|
||||
PR_WARN("ch[%d]:post timeout[%d]\n", ch,
|
||||
ppost->cur_post_buf->seq);
|
||||
dim_ddbg_mod_save(eDI_DBG_MOD_POST_TIMEOUT, ch, 0);
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_TIMEOUT;
|
||||
reflesh = true;
|
||||
}
|
||||
}
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
void dpst_timeout(unsigned int ch)
|
||||
{
|
||||
hpst_dbg_mem_pd_trig(0);
|
||||
post_close_new();
|
||||
#if 0
|
||||
di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP);
|
||||
di_post_reset();
|
||||
#endif
|
||||
dimh_pst_trig_resize();
|
||||
}
|
||||
|
||||
bool dpst_step_timeout(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
bool reflesh = false;
|
||||
ulong flags = 0;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
dpst_timeout(ch);
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_post_de_done_buf_config(ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
pst->flg_int_done = false;
|
||||
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_done(void)/*this step no use ?*/
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
bool reflesh = false;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
/* dim_post_de_done_buf_config(ch);*/
|
||||
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
const struct di_func_tab_s di_pst_func_tab[] = {
|
||||
{eDI_PST_ST_EXIT, NULL},
|
||||
{eDI_PST_ST_IDLE, dpst_step_idle},
|
||||
{eDI_PST_ST_CHECK, dpst_step_check},
|
||||
{eDI_PST_ST_SET, dpst_step_set},
|
||||
{eDI_PST_ST_WAIT_INT, dpst_step_wait_int},
|
||||
{eDI_PST_ST_TIMEOUT, dpst_step_timeout},
|
||||
{eDI_PST_ST_DONE, dpst_step_done},
|
||||
};
|
||||
|
||||
const char * const dpst_state_name[] = {
|
||||
"EXIT",
|
||||
"IDLE", /*swith to next channel?*/
|
||||
"CHECK",
|
||||
"SET",
|
||||
"WAIT_INT",
|
||||
"TIMEOUT",
|
||||
"DONE",
|
||||
};
|
||||
|
||||
const char *dpst_state_name_get(enum eDI_PST_ST state)
|
||||
{
|
||||
if (state > eDI_PST_ST_DONE)
|
||||
return "nothing";
|
||||
|
||||
return dpst_state_name[state];
|
||||
}
|
||||
|
||||
bool dpst_can_exit(unsigned int ch)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
bool ret = false;
|
||||
|
||||
if (ch != pst->curr_ch) {
|
||||
ret = true;
|
||||
} else {
|
||||
if (pst->state <= eDI_PST_ST_IDLE)
|
||||
ret = true;
|
||||
}
|
||||
pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n",
|
||||
__func__,
|
||||
ch, pst->curr_ch,
|
||||
dpst_state_name_get(pst->state),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool dpst_process_step2(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
enum eDI_PST_ST pst_st = pst->state;
|
||||
unsigned int ch;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
if (pst_st > eDI_PST_ST_EXIT)
|
||||
dim_recycle_post_back(ch);
|
||||
|
||||
if ((pst_st <= eDI_PST_ST_DONE) &&
|
||||
di_pst_func_tab[pst_st].func)
|
||||
return di_pst_func_tab[pst_st].func();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void dpst_dbg_f_trig(unsigned int cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
if (down_interruptible(&tsk->sem)) {
|
||||
PR_ERR("%s:can't get sem\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*set on/off and trig*/
|
||||
if (cmd & 0x10) {
|
||||
pst->dbg_f_en = 1;
|
||||
pst->dbg_f_cnt = cmd & 0xf;
|
||||
pst->dbg_f_lstate = pst->state;
|
||||
} else {
|
||||
pst->dbg_f_en = 0;
|
||||
}
|
||||
|
||||
up(&tsk->sem);
|
||||
}
|
||||
|
||||
void dpst_process(void)
|
||||
{
|
||||
bool reflesh;
|
||||
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
if (pst->dbg_f_en) {
|
||||
if (pst->dbg_f_cnt) {
|
||||
dpst_process_step2();
|
||||
pst->dbg_f_cnt--;
|
||||
}
|
||||
if (pst->dbg_f_lstate != pst->state) {
|
||||
pr_info("ch[%d]:state:%s->%s\n",
|
||||
pst->curr_ch,
|
||||
dpst_state_name_get(pst->dbg_f_lstate),
|
||||
dpst_state_name_get(pst->state));
|
||||
|
||||
pst->dbg_f_lstate = pst->state;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
reflesh = true;
|
||||
|
||||
while (reflesh)
|
||||
reflesh = dpst_process_step2();
|
||||
}
|
||||
27
drivers/amlogic/media/di_multi/di_post.h
Normal file
27
drivers/amlogic/media/di_multi/di_post.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_post.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_POST_H__
|
||||
#define __DI_POST_H__
|
||||
|
||||
void dpost_init(void);
|
||||
void dpst_process(void);
|
||||
const char *dpst_state_name_get(enum eDI_PST_ST state);
|
||||
void dpst_dbg_f_trig(unsigned int cmd);
|
||||
bool dpst_can_exit(unsigned int ch);
|
||||
|
||||
#endif /*__DI_POST_H__*/
|
||||
628
drivers/amlogic/media/di_multi/di_pps.c
Normal file
628
drivers/amlogic/media/di_multi/di_pps.c
Normal file
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pps.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/amlogic/media/registers/regs/di_regs.h>
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "di_pps.h"
|
||||
#include "register.h"
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#if 0
|
||||
/* pps filter coefficients */
|
||||
#define COEF_BICUBIC 0
|
||||
#define COEF_3POINT_TRIANGLE 1
|
||||
#define COEF_4POINT_TRIANGLE 2
|
||||
#define COEF_BILINEAR 3
|
||||
#define COEF_2POINT_BILINEAR 4
|
||||
#define COEF_BICUBIC_SHARP 5
|
||||
#define COEF_3POINT_TRIANGLE_SHARP 6
|
||||
#define COEF_3POINT_BSPLINE 7
|
||||
#define COEF_4POINT_BSPLINE 8
|
||||
#define COEF_3D_FILTER 9
|
||||
#define COEF_NULL 0xff
|
||||
#define TOTAL_FILTERS 10
|
||||
|
||||
#define MAX_NONLINEAR_FACTOR 0x40
|
||||
|
||||
const u32 vpp_filter_coefs_bicubic_sharp[] = {
|
||||
3,
|
||||
33 | 0x8000,
|
||||
/* 0x01f80090, 0x01f80100, 0xff7f0200, 0xfe7f0300, */
|
||||
0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300,
|
||||
0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
|
||||
0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
|
||||
0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
|
||||
0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
|
||||
0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
|
||||
0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
|
||||
0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
|
||||
0xf84848f8
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_bicubic[] = {
|
||||
4,
|
||||
33,
|
||||
0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300,
|
||||
0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
|
||||
0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
|
||||
0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
|
||||
0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
|
||||
0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
|
||||
0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
|
||||
0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
|
||||
0xf84848f8
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_bilinear[] = {
|
||||
4,
|
||||
33,
|
||||
0x00800000, 0x007e0200, 0x007c0400, 0x007a0600,
|
||||
0x00780800, 0x00760a00, 0x00740c00, 0x00720e00,
|
||||
0x00701000, 0x006e1200, 0x006c1400, 0x006a1600,
|
||||
0x00681800, 0x00661a00, 0x00641c00, 0x00621e00,
|
||||
0x00602000, 0x005e2200, 0x005c2400, 0x005a2600,
|
||||
0x00582800, 0x00562a00, 0x00542c00, 0x00522e00,
|
||||
0x00503000, 0x004e3200, 0x004c3400, 0x004a3600,
|
||||
0x00483800, 0x00463a00, 0x00443c00, 0x00423e00,
|
||||
0x00404000
|
||||
};
|
||||
|
||||
const u32 vpp_3d_filter_coefs_bilinear[] = {
|
||||
2,
|
||||
33,
|
||||
0x80000000, 0x7e020000, 0x7c040000, 0x7a060000,
|
||||
0x78080000, 0x760a0000, 0x740c0000, 0x720e0000,
|
||||
0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
|
||||
0x68180000, 0x661a0000, 0x641c0000, 0x621e0000,
|
||||
0x60200000, 0x5e220000, 0x5c240000, 0x5a260000,
|
||||
0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
|
||||
0x50300000, 0x4e320000, 0x4c340000, 0x4a360000,
|
||||
0x48380000, 0x463a0000, 0x443c0000, 0x423e0000,
|
||||
0x40400000
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_3point_triangle[] = {
|
||||
3,
|
||||
33,
|
||||
0x40400000, 0x3f400100, 0x3d410200, 0x3c410300,
|
||||
0x3a420400, 0x39420500, 0x37430600, 0x36430700,
|
||||
0x35430800, 0x33450800, 0x32450900, 0x31450a00,
|
||||
0x30450b00, 0x2e460c00, 0x2d460d00, 0x2c470d00,
|
||||
0x2b470e00, 0x29480f00, 0x28481000, 0x27481100,
|
||||
0x26491100, 0x25491200, 0x24491300, 0x234a1300,
|
||||
0x224a1400, 0x214a1500, 0x204a1600, 0x1f4b1600,
|
||||
0x1e4b1700, 0x1d4b1800, 0x1c4c1800, 0x1b4c1900,
|
||||
0x1a4c1a00
|
||||
};
|
||||
|
||||
/* point_num =4, filt_len =4, group_num = 64, [1 2 1] */
|
||||
const u32 vpp_filter_coefs_4point_triangle[] = {
|
||||
4,
|
||||
33,
|
||||
0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101,
|
||||
0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303,
|
||||
0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505,
|
||||
0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707,
|
||||
0x18382808, 0x18382808, 0x17372909, 0x17372909,
|
||||
0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b,
|
||||
0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d,
|
||||
0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f,
|
||||
0x10303010
|
||||
};
|
||||
|
||||
/*
|
||||
*4th order (cubic) b-spline
|
||||
*filt_cubic point_num =4, filt_len =4, group_num = 64, [1 5 1]
|
||||
*/
|
||||
const u32 vpp_filter_coefs_4point_bspline[] = {
|
||||
4,
|
||||
33,
|
||||
0x15561500, 0x14561600, 0x13561700, 0x12561800,
|
||||
0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
|
||||
0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
|
||||
0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
|
||||
0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
|
||||
0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
|
||||
0x05473301, 0x05463401, 0x04453601, 0x04433702,
|
||||
0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
|
||||
0x033d3d03
|
||||
};
|
||||
|
||||
/*3rd order (quadratic) b-spline*/
|
||||
/*filt_quadratic, point_num =3, filt_len =3, group_num = 64, [1 6 1] */
|
||||
const u32 vpp_filter_coefs_3point_bspline[] = {
|
||||
3,
|
||||
33,
|
||||
0x40400000, 0x3e420000, 0x3c440000, 0x3a460000,
|
||||
0x38480000, 0x364a0000, 0x344b0100, 0x334c0100,
|
||||
0x314e0100, 0x304f0100, 0x2e500200, 0x2c520200,
|
||||
0x2a540200, 0x29540300, 0x27560300, 0x26570300,
|
||||
0x24580400, 0x23590400, 0x215a0500, 0x205b0500,
|
||||
0x1e5c0600, 0x1d5c0700, 0x1c5d0700, 0x1a5e0800,
|
||||
0x195e0900, 0x185e0a00, 0x175f0a00, 0x15600b00,
|
||||
0x14600c00, 0x13600d00, 0x12600e00, 0x11600f00,
|
||||
0x10601000
|
||||
};
|
||||
|
||||
/*filt_triangle, point_num =3, filt_len =2.6, group_num = 64, [1 7 1] */
|
||||
const u32 vpp_filter_coefs_3point_triangle_sharp[] = {
|
||||
3,
|
||||
33,
|
||||
0x40400000, 0x3e420000, 0x3d430000, 0x3b450000,
|
||||
0x3a460000, 0x38480000, 0x37490000, 0x354b0000,
|
||||
0x344c0000, 0x324e0000, 0x314f0000, 0x2f510000,
|
||||
0x2e520000, 0x2c540000, 0x2b550000, 0x29570000,
|
||||
0x28580000, 0x265a0000, 0x245c0000, 0x235d0000,
|
||||
0x215f0000, 0x20600000, 0x1e620000, 0x1d620100,
|
||||
0x1b620300, 0x19630400, 0x17630600, 0x15640700,
|
||||
0x14640800, 0x12640a00, 0x11640b00, 0x0f650c00,
|
||||
0x0d660d00
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_2point_binilear[] = {
|
||||
2,
|
||||
33,
|
||||
0x80000000, 0x7e020000, 0x7c040000, 0x7a060000,
|
||||
0x78080000, 0x760a0000, 0x740c0000, 0x720e0000,
|
||||
0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
|
||||
0x68180000, 0x661a0000, 0x641c0000, 0x621e0000,
|
||||
0x60200000, 0x5e220000, 0x5c240000, 0x5a260000,
|
||||
0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
|
||||
0x50300000, 0x4e320000, 0x4c340000, 0x4a360000,
|
||||
0x48380000, 0x463a0000, 0x443c0000, 0x423e0000,
|
||||
0x40400000
|
||||
};
|
||||
|
||||
static const u32 *filter_table[] = {
|
||||
vpp_filter_coefs_bicubic,
|
||||
vpp_filter_coefs_3point_triangle,
|
||||
vpp_filter_coefs_4point_triangle,
|
||||
vpp_filter_coefs_bilinear,
|
||||
vpp_filter_coefs_2point_binilear,
|
||||
vpp_filter_coefs_bicubic_sharp,
|
||||
vpp_filter_coefs_3point_triangle_sharp,
|
||||
vpp_filter_coefs_3point_bspline,
|
||||
vpp_filter_coefs_4point_bspline,
|
||||
vpp_3d_filter_coefs_bilinear
|
||||
};
|
||||
|
||||
static int chroma_filter_table[] = {
|
||||
COEF_BICUBIC, /* bicubic */
|
||||
COEF_3POINT_TRIANGLE,
|
||||
COEF_4POINT_TRIANGLE,
|
||||
COEF_4POINT_TRIANGLE, /* bilinear */
|
||||
COEF_2POINT_BILINEAR,
|
||||
COEF_3POINT_TRIANGLE, /* bicubic_sharp */
|
||||
COEF_3POINT_TRIANGLE, /* 3point_triangle_sharp */
|
||||
COEF_3POINT_TRIANGLE, /* 3point_bspline */
|
||||
COEF_4POINT_TRIANGLE, /* 4point_bspline */
|
||||
COEF_3D_FILTER /* can not change */
|
||||
};
|
||||
|
||||
static unsigned int vert_scaler_filter = 0xff;
|
||||
module_param(vert_scaler_filter, uint, 0664);
|
||||
MODULE_PARM_DESC(vert_scaler_filter, "vert_scaler_filter");
|
||||
|
||||
static unsigned int vert_chroma_scaler_filter = 0xff;
|
||||
module_param(vert_chroma_scaler_filter, uint, 0664);
|
||||
MODULE_PARM_DESC(vert_chroma_scaler_filter, "vert_chroma_scaler_filter");
|
||||
|
||||
static unsigned int horz_scaler_filter = 0xff;
|
||||
module_param(horz_scaler_filter, uint, 0664);
|
||||
MODULE_PARM_DESC(horz_scaler_filter, "horz_scaler_filter");
|
||||
|
||||
bool pre_scaler_en = true;
|
||||
module_param(pre_scaler_en, bool, 0664);
|
||||
MODULE_PARM_DESC(pre_scaler_en, "pre_scaler_en");
|
||||
#endif
|
||||
/*bicubic*/
|
||||
static const unsigned int di_filt_coef0[] = {
|
||||
0x00800000,
|
||||
0x007f0100,
|
||||
0xff7f0200,
|
||||
0xfe7f0300,
|
||||
0xfd7e0500,
|
||||
0xfc7e0600,
|
||||
0xfb7d0800,
|
||||
0xfb7c0900,
|
||||
0xfa7b0b00,
|
||||
0xfa7a0dff,
|
||||
0xf9790fff,
|
||||
0xf97711ff,
|
||||
0xf87613ff,
|
||||
0xf87416fe,
|
||||
0xf87218fe,
|
||||
0xf8701afe,
|
||||
0xf76f1dfd,
|
||||
0xf76d1ffd,
|
||||
0xf76b21fd,
|
||||
0xf76824fd,
|
||||
0xf76627fc,
|
||||
0xf76429fc,
|
||||
0xf7612cfc,
|
||||
0xf75f2ffb,
|
||||
0xf75d31fb,
|
||||
0xf75a34fb,
|
||||
0xf75837fa,
|
||||
0xf7553afa,
|
||||
0xf8523cfa,
|
||||
0xf8503ff9,
|
||||
0xf84d42f9,
|
||||
0xf84a45f9,
|
||||
0xf84848f8
|
||||
};
|
||||
|
||||
/* 2 point bilinear */
|
||||
static const unsigned int di_filt_coef1[] = {
|
||||
0x00800000,
|
||||
0x007e0200,
|
||||
0x007c0400,
|
||||
0x007a0600,
|
||||
0x00780800,
|
||||
0x00760a00,
|
||||
0x00740c00,
|
||||
0x00720e00,
|
||||
0x00701000,
|
||||
0x006e1200,
|
||||
0x006c1400,
|
||||
0x006a1600,
|
||||
0x00681800,
|
||||
0x00661a00,
|
||||
0x00641c00,
|
||||
0x00621e00,
|
||||
0x00602000,
|
||||
0x005e2200,
|
||||
0x005c2400,
|
||||
0x005a2600,
|
||||
0x00582800,
|
||||
0x00562a00,
|
||||
0x00542c00,
|
||||
0x00522e00,
|
||||
0x00503000,
|
||||
0x004e3200,
|
||||
0x004c3400,
|
||||
0x004a3600,
|
||||
0x00483800,
|
||||
0x00463a00,
|
||||
0x00443c00,
|
||||
0x00423e00,
|
||||
0x00404000
|
||||
};
|
||||
|
||||
/* 2 point bilinear, bank_length == 2*/
|
||||
static const unsigned int di_filt_coef2[] = {
|
||||
0x80000000,
|
||||
0x7e020000,
|
||||
0x7c040000,
|
||||
0x7a060000,
|
||||
0x78080000,
|
||||
0x760a0000,
|
||||
0x740c0000,
|
||||
0x720e0000,
|
||||
0x70100000,
|
||||
0x6e120000,
|
||||
0x6c140000,
|
||||
0x6a160000,
|
||||
0x68180000,
|
||||
0x661a0000,
|
||||
0x641c0000,
|
||||
0x621e0000,
|
||||
0x60200000,
|
||||
0x5e220000,
|
||||
0x5c240000,
|
||||
0x5a260000,
|
||||
0x58280000,
|
||||
0x562a0000,
|
||||
0x542c0000,
|
||||
0x522e0000,
|
||||
0x50300000,
|
||||
0x4e320000,
|
||||
0x4c340000,
|
||||
0x4a360000,
|
||||
0x48380000,
|
||||
0x463a0000,
|
||||
0x443c0000,
|
||||
0x423e0000,
|
||||
0x40400000
|
||||
};
|
||||
|
||||
#define ZOOM_BITS 20
|
||||
#define PHASE_BITS 16
|
||||
|
||||
static enum f2v_vphase_type_e top_conv_type = F2V_P2P;
|
||||
static enum f2v_vphase_type_e bot_conv_type = F2V_P2P;
|
||||
static unsigned int prehsc_en;
|
||||
static unsigned int prevsc_en;
|
||||
|
||||
static const unsigned char f2v_420_in_pos_luma[F2V_TYPE_MAX] = {
|
||||
0, 2, 0, 2, 0, 0, 0, 2, 0};
|
||||
#if 0
|
||||
static const unsigned char f2v_420_in_pos_chroma[F2V_TYPE_MAX] = {
|
||||
1, 5, 1, 5, 2, 2, 1, 5, 2};
|
||||
#endif
|
||||
static const unsigned char f2v_420_out_pos[F2V_TYPE_MAX] = {
|
||||
0, 2, 2, 0, 0, 2, 0, 0, 0};
|
||||
|
||||
static void f2v_get_vertical_phase(unsigned int zoom_ratio,
|
||||
enum f2v_vphase_type_e type,
|
||||
unsigned char bank_length,
|
||||
struct pps_f2v_vphase_s *vphase)
|
||||
{
|
||||
int offset_in, offset_out;
|
||||
|
||||
/* luma */
|
||||
offset_in = f2v_420_in_pos_luma[type] << PHASE_BITS;
|
||||
offset_out = (f2v_420_out_pos[type] * zoom_ratio)
|
||||
>> (ZOOM_BITS - PHASE_BITS);
|
||||
|
||||
vphase->rcv_num = bank_length;
|
||||
if (bank_length == 4 || bank_length == 3)
|
||||
vphase->rpt_num = 1;
|
||||
else
|
||||
vphase->rpt_num = 0;
|
||||
|
||||
if (offset_in > offset_out) {
|
||||
vphase->rpt_num = vphase->rpt_num + 1;
|
||||
vphase->phase =
|
||||
((4 << PHASE_BITS) + offset_out - offset_in) >> 2;
|
||||
} else {
|
||||
while ((offset_in + (4 << PHASE_BITS)) <= offset_out) {
|
||||
if (vphase->rpt_num == 1)
|
||||
vphase->rpt_num = 0;
|
||||
else
|
||||
vphase->rcv_num++;
|
||||
offset_in += 4 << PHASE_BITS;
|
||||
}
|
||||
vphase->phase = (offset_out - offset_in) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* patch 1: inp scaler 0: di wr scaler
|
||||
* support: TM2
|
||||
* not support: SM1
|
||||
*/
|
||||
void dim_pps_config(unsigned char path, int src_w, int src_h,
|
||||
int dst_w, int dst_h)
|
||||
{
|
||||
struct pps_f2v_vphase_s vphase;
|
||||
|
||||
int i;
|
||||
int hsc_en = 0, vsc_en = 0;
|
||||
int vsc_double_line_mode;
|
||||
unsigned int p_src_w, p_src_h;
|
||||
unsigned int vert_phase_step, horz_phase_step;
|
||||
unsigned char top_rcv_num, bot_rcv_num;
|
||||
unsigned char top_rpt_num, bot_rpt_num;
|
||||
unsigned short top_vphase, bot_vphase;
|
||||
unsigned char is_frame;
|
||||
int vert_bank_length = 4;
|
||||
|
||||
const unsigned int *filt_coef0 = di_filt_coef0;
|
||||
/*unsigned int *filt_coef1 = di_filt_coef1;*/
|
||||
const unsigned int *filt_coef2 = di_filt_coef2;
|
||||
|
||||
vsc_double_line_mode = 0;
|
||||
|
||||
if (src_h != dst_h)
|
||||
vsc_en = 1;
|
||||
if (src_w != dst_w)
|
||||
hsc_en = 1;
|
||||
/* config hdr size */
|
||||
Wr_reg_bits(DI_HDR_IN_HSIZE, dst_w, 0, 13);
|
||||
Wr_reg_bits(DI_HDR_IN_VSIZE, dst_h, 0, 13);
|
||||
p_src_w = (prehsc_en ? ((src_w + 1) >> 1) : src_w);
|
||||
p_src_h = prevsc_en ? ((src_h + 1) >> 1) : src_h;
|
||||
|
||||
Wr(DI_SC_HOLD_LINE, 0x10);
|
||||
|
||||
if (p_src_w > 2048) {
|
||||
/*force vert bank length = 2*/
|
||||
vert_bank_length = 2;
|
||||
vsc_double_line_mode = 1;
|
||||
}
|
||||
|
||||
/*write vert filter coefs*/
|
||||
Wr(DI_SC_COEF_IDX, 0x0000);
|
||||
for (i = 0; i < 33; i++) {
|
||||
if (vert_bank_length == 2)
|
||||
Wr(DI_SC_COEF, filt_coef2[i]); /*bilinear*/
|
||||
else
|
||||
Wr(DI_SC_COEF, filt_coef0[i]); /*bicubic*/
|
||||
}
|
||||
|
||||
/*write horz filter coefs*/
|
||||
Wr(DI_SC_COEF_IDX, 0x0100);
|
||||
for (i = 0; i < 33; i++)
|
||||
Wr(DI_SC_COEF, filt_coef0[i]); /*bicubic*/
|
||||
|
||||
if (p_src_h > 2048)
|
||||
vert_phase_step = ((p_src_h << 18) / dst_h) << 2;
|
||||
else
|
||||
vert_phase_step = (p_src_h << 20) / dst_h;
|
||||
if (p_src_w > 2048)
|
||||
horz_phase_step = ((p_src_w << 18) / dst_w) << 2;
|
||||
else
|
||||
horz_phase_step = (p_src_w << 20) / dst_w;
|
||||
|
||||
is_frame = ((top_conv_type == F2V_IT2P) ||
|
||||
(top_conv_type == F2V_IB2P) ||
|
||||
(top_conv_type == F2V_P2P));
|
||||
|
||||
if (is_frame) {
|
||||
f2v_get_vertical_phase(vert_phase_step, top_conv_type,
|
||||
vert_bank_length, &vphase);
|
||||
top_rcv_num = vphase.rcv_num;
|
||||
top_rpt_num = vphase.rpt_num;
|
||||
top_vphase = vphase.phase;
|
||||
|
||||
bot_rcv_num = 0;
|
||||
bot_rpt_num = 0;
|
||||
bot_vphase = 0;
|
||||
} else {
|
||||
f2v_get_vertical_phase(vert_phase_step, top_conv_type,
|
||||
vert_bank_length, &vphase);
|
||||
top_rcv_num = vphase.rcv_num;
|
||||
top_rpt_num = vphase.rpt_num;
|
||||
top_vphase = vphase.phase;
|
||||
|
||||
f2v_get_vertical_phase(vert_phase_step, bot_conv_type,
|
||||
vert_bank_length, &vphase);
|
||||
bot_rcv_num = vphase.rcv_num;
|
||||
bot_rpt_num = vphase.rpt_num;
|
||||
bot_vphase = vphase.phase;
|
||||
}
|
||||
vert_phase_step = (vert_phase_step << 4);
|
||||
horz_phase_step = (horz_phase_step << 4);
|
||||
|
||||
Wr(DI_SC_LINE_IN_LENGTH, src_w);
|
||||
Wr(DI_SC_PIC_IN_HEIGHT, src_h);
|
||||
Wr(DI_VSC_REGION12_STARTP, 0);
|
||||
Wr(DI_VSC_REGION34_STARTP, ((dst_h << 16) | dst_h));
|
||||
Wr(DI_VSC_REGION4_ENDP, (dst_h - 1));
|
||||
|
||||
Wr(DI_VSC_START_PHASE_STEP, vert_phase_step);
|
||||
Wr(DI_VSC_REGION0_PHASE_SLOPE, 0);
|
||||
Wr(DI_VSC_REGION1_PHASE_SLOPE, 0);
|
||||
Wr(DI_VSC_REGION3_PHASE_SLOPE, 0);
|
||||
Wr(DI_VSC_REGION4_PHASE_SLOPE, 0);
|
||||
|
||||
Wr(DI_VSC_PHASE_CTRL,
|
||||
((vsc_double_line_mode << 17) |
|
||||
(!is_frame) << 16) |
|
||||
(0 << 15) |
|
||||
(bot_rpt_num << 13) |
|
||||
(bot_rcv_num << 8) |
|
||||
(0 << 7) |
|
||||
(top_rpt_num << 5) |
|
||||
(top_rcv_num));
|
||||
Wr(DI_VSC_INI_PHASE, (bot_vphase << 16) | top_vphase);
|
||||
Wr(DI_HSC_REGION12_STARTP, 0);
|
||||
Wr(DI_HSC_REGION34_STARTP, (dst_w << 16) | dst_w);
|
||||
Wr(DI_HSC_REGION4_ENDP, dst_w - 1);
|
||||
|
||||
Wr(DI_HSC_START_PHASE_STEP, horz_phase_step);
|
||||
Wr(DI_HSC_REGION0_PHASE_SLOPE, 0);
|
||||
Wr(DI_HSC_REGION1_PHASE_SLOPE, 0);
|
||||
Wr(DI_HSC_REGION3_PHASE_SLOPE, 0);
|
||||
Wr(DI_HSC_REGION4_PHASE_SLOPE, 0);
|
||||
|
||||
Wr(DI_HSC_PHASE_CTRL, (1 << 21) | (4 << 16) | 0);
|
||||
Wr_reg_bits(DI_SC_TOP_CTRL, (path ? 3 : 0), 29, 2);
|
||||
Wr(DI_SC_MISC,
|
||||
(prevsc_en << 21) |
|
||||
(prehsc_en << 20) | /* prehsc_en */
|
||||
(prevsc_en << 19) | /* prevsc_en */
|
||||
(vsc_en << 18) | /* vsc_en */
|
||||
(hsc_en << 17) | /* hsc_en */
|
||||
((vsc_en | hsc_en) << 16) | /* sc_top_en */
|
||||
(1 << 15) | /* vd1 sc out enable */
|
||||
(0 << 12) | /* horz nonlinear 4region enable */
|
||||
(4 << 8) | /* horz scaler bank length */
|
||||
(0 << 5) | /* vert scaler phase field enable */
|
||||
(0 << 4) | /* vert nonlinear 4region enable */
|
||||
(vert_bank_length << 0) /* vert scaler bank length */
|
||||
);
|
||||
|
||||
pr_info("[pps] %s input %d %d output %d %d.\n",
|
||||
path ? "pre" : "post", src_w, src_h, dst_w, dst_h);
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x374e ~ 0x376d, 20 regs
|
||||
*/
|
||||
void dim_dump_pps_reg(unsigned int base_addr)
|
||||
{
|
||||
unsigned int i = 0x374e;
|
||||
|
||||
pr_info("-----dump pps start-----\n");
|
||||
for (i = 0x374e; i < 0x376e; i++) {
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2),
|
||||
i, dim_RDMA_RD(i));
|
||||
}
|
||||
pr_info("-----dump pps end-----\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* di pre h scaling down function
|
||||
* only have h scaling down
|
||||
* support: sm1 tm2 ...
|
||||
* 0x37b0 ~ 0x37b5
|
||||
*/
|
||||
void dim_inp_hsc_setting(u32 src_w, u32 dst_w)
|
||||
{
|
||||
u32 i;
|
||||
u32 hsc_en;
|
||||
u32 horz_phase_step;
|
||||
const int *filt_coef0 = di_filt_coef0;
|
||||
/*int *filt_coef1 = di_filt_coef1;*/
|
||||
/*int *filt_coef2 = di_filt_coef2;*/
|
||||
|
||||
if (src_w == dst_w) {
|
||||
hsc_en = 0;
|
||||
} else {
|
||||
hsc_en = 1;
|
||||
/*write horz filter coefs*/
|
||||
dim_RDMA_WR(DI_VIU_HSC_COEF_IDX, 0x0100);
|
||||
for (i = 0; i < 33; i++) /*bicubic*/
|
||||
dim_RDMA_WR(DI_VIU_HSC_COEF, filt_coef0[i]);
|
||||
|
||||
horz_phase_step = (src_w << 20) / dst_w;
|
||||
horz_phase_step = (horz_phase_step << 4);
|
||||
dim_RDMA_WR(DI_VIU_HSC_WIDTHM1,
|
||||
(src_w - 1) << 16 | (dst_w - 1));
|
||||
dim_RDMA_WR(DI_VIU_HSC_PHASE_STEP, horz_phase_step);
|
||||
dim_RDMA_WR(DI_VIU_HSC_PHASE_CTRL, 0);
|
||||
}
|
||||
dim_RDMA_WR(DI_VIU_HSC_CTRL,
|
||||
(4 << 20) | /* initial receive number*/
|
||||
(0 << 12) | /* initial pixel ptr*/
|
||||
(1 << 10) | /* repeat first pixel number*/
|
||||
(0 << 8) | /* sp422 mode*/
|
||||
(4 << 4) | /* horz scaler bank length*/
|
||||
(0 << 2) | /* phase0 always en*/
|
||||
(0 << 1) | /* nearest_en*/
|
||||
(hsc_en << 0)); /* hsc_en*/
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x37b0 ~ 0x37b5
|
||||
*/
|
||||
void dim_dump_hdownscler_reg(unsigned int base_addr)
|
||||
{
|
||||
unsigned int i = 0x374e;
|
||||
|
||||
pr_info("-----dump hdownscler start-----\n");
|
||||
for (i = 0x37b0; i < 0x37b5; i++) {
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2),
|
||||
i, dim_RDMA_RD(i));
|
||||
}
|
||||
pr_info("-----dump hdownscler end-----\n");
|
||||
}
|
||||
|
||||
int dim_seq_file_module_para_pps(struct seq_file *seq)
|
||||
{
|
||||
seq_puts(seq, "pps---------------\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
112
drivers/amlogic/media/di_multi/di_pps.h
Normal file
112
drivers/amlogic/media/di_multi/di_pps.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pps.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_PPS_H
|
||||
#define DI_PPS_H
|
||||
#include <linux/amlogic/media/video_sink/video.h>
|
||||
#include <linux/amlogic/media/video_sink/vpp.h>
|
||||
#if 0
|
||||
#define VPP_FLAG_WIDEMODE_MASK 0x0000000F
|
||||
#define VPP_FLAG_INTERLACE_OUT 0x00000010
|
||||
#define VPP_FLAG_INTERLACE_IN 0x00000020
|
||||
#define VPP_FLAG_CBCR_SEPARATE 0x00000040
|
||||
#define VPP_FLAG_ZOOM_SHORTSIDE 0x00000080
|
||||
#define VPP_FLAG_AR_MASK 0x0003ff00
|
||||
#define VPP_FLAG_AR_BITS 8
|
||||
#define VPP_FLAG_PORTRAIT_MODE 0x00040000
|
||||
#define VPP_FLAG_VSCALE_DISABLE 0x00080000
|
||||
|
||||
#define IDX_H (2 << 8)
|
||||
#define IDX_V_Y (1 << 13)
|
||||
#define IDX_V_CBCR ((1 << 13) | (1 << 8))
|
||||
|
||||
#define ASPECT_4_3 ((3 << 8) / 4)
|
||||
#define ASPECT_16_9 ((9 << 8) / 16)
|
||||
|
||||
#define SPEED_CHECK_DONE 0
|
||||
#define SPEED_CHECK_HSKIP 1
|
||||
#define SPEED_CHECK_VSKIP 2
|
||||
|
||||
enum f2v_vphase_type_e {
|
||||
F2V_IT2IT = 0,
|
||||
F2V_IB2IB,
|
||||
F2V_IT2IB,
|
||||
F2V_IB2IT,
|
||||
F2V_P2IT,
|
||||
F2V_P2IB,
|
||||
F2V_IT2P,
|
||||
F2V_IB2P,
|
||||
F2V_P2P,
|
||||
F2V_TYPE_MAX
|
||||
}; /* frame to video conversion type */
|
||||
#endif
|
||||
|
||||
enum hdr2_scaler_e {
|
||||
hdr2_scaler_postdi = 0,
|
||||
hdr2_scaler_predi = 1,
|
||||
};
|
||||
|
||||
struct pps_f2v_vphase_s {
|
||||
unsigned char rcv_num;
|
||||
unsigned char rpt_num;
|
||||
unsigned short phase;
|
||||
};
|
||||
|
||||
struct ppsfilter_mode_s {
|
||||
u32 pps_hf_start_phase_step;
|
||||
u32 pps_hf_start_phase_slope;
|
||||
u32 pps_hf_end_phase_slope;
|
||||
const u32 *pps_vert_coeff;
|
||||
const u32 *pps_horz_coeff;
|
||||
u32 pps_sc_misc_;
|
||||
u32 pps_vsc_start_phase_step;
|
||||
u32 pps_hsc_start_phase_step;
|
||||
bool pps_pre_vsc_en;
|
||||
bool pps_pre_hsc_en;
|
||||
u32 pps_vert_filter;
|
||||
u32 pps_horz_filter;
|
||||
const u32 *pps_chroma_coeff;
|
||||
u32 pps_chroma_filter_en;
|
||||
};
|
||||
|
||||
struct pps_frame_par_s {
|
||||
u32 pps_vsc_startp;
|
||||
u32 pps_vsc_endp;
|
||||
u32 pps_hsc_startp;
|
||||
u32 pps_hsc_linear_startp;
|
||||
u32 pps_hsc_linear_endp;
|
||||
u32 pps_hsc_endp;
|
||||
u32 VPP_hf_ini_phase_;
|
||||
struct f2v_vphase_s VPP_vf_ini_phase_[9];
|
||||
u32 pps_pic_in_height_;
|
||||
u32 pps_line_in_length_;
|
||||
struct ppsfilter_mode_s pps_filter;
|
||||
u32 pps_3d_mode;
|
||||
u32 trans_fmt;
|
||||
/* bit[1:0] 0: 1 pic,1:two pic one buf,2:tow pic two buf */
|
||||
/* bit[2]0:select pic0,1:select pic1 */
|
||||
/* bit[3]0:pic0 first,1:pic1 first */
|
||||
bool pps_3d_scale;
|
||||
};
|
||||
|
||||
void dim_pps_config(unsigned char path, int src_w, int src_h,
|
||||
int dst_w, int dst_h);
|
||||
void dim_dump_pps_reg(unsigned int base_addr);
|
||||
void dim_inp_hsc_setting(u32 src_w, u32 dst_w);
|
||||
void dim_dump_hdownscler_reg(unsigned int base_addr);
|
||||
|
||||
#endif
|
||||
1966
drivers/amlogic/media/di_multi/di_prc.c
Normal file
1966
drivers/amlogic/media/di_multi/di_prc.c
Normal file
File diff suppressed because it is too large
Load Diff
131
drivers/amlogic/media/di_multi/di_prc.h
Normal file
131
drivers/amlogic/media/di_multi/di_prc.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_prc.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_PRC_H__
|
||||
#define __DI_PRC_H__
|
||||
|
||||
bool dip_prob(void);
|
||||
void dip_exit(void);
|
||||
|
||||
void dip_even_reg_init_val(unsigned int ch);
|
||||
void dip_even_unreg_val(unsigned int ch);
|
||||
|
||||
/************************/
|
||||
/* CMA */
|
||||
/************************/
|
||||
void dip_wq_cma_run(unsigned char ch, bool reg_cmd);
|
||||
bool dip_cma_st_is_ready(unsigned int ch);
|
||||
bool dip_cma_st_is_idle(unsigned int ch);
|
||||
bool dip_cma_st_is_idl_all(void);
|
||||
enum eDI_CMA_ST dip_cma_get_st(unsigned int ch);
|
||||
void dip_cma_st_set_ready_all(void);
|
||||
void dip_cma_close(void);
|
||||
const char *di_cma_dbg_get_st_name(unsigned int ch);
|
||||
|
||||
/*************************/
|
||||
/* STATE*/
|
||||
/*************************/
|
||||
bool dip_event_reg_chst(unsigned int ch);
|
||||
bool dip_event_unreg_chst(unsigned int ch);
|
||||
void dip_chst_process_reg(unsigned int ch);
|
||||
|
||||
void dip_hw_process(void);
|
||||
|
||||
void dip_chst_process_ch(void);
|
||||
bool dip_chst_change_2unreg(void);
|
||||
|
||||
enum eDI_TOP_STATE dip_chst_get(unsigned int ch);
|
||||
const char *dip_chst_get_name_curr(unsigned int ch);
|
||||
const char *dip_chst_get_name(enum eDI_TOP_STATE chst);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* summmary variable
|
||||
*
|
||||
**************************************/
|
||||
void di_sum_reg_init(unsigned int ch);
|
||||
void di_sum_set(unsigned int ch, enum eDI_SUM id, unsigned int val);
|
||||
unsigned int di_sum_inc(unsigned int ch, enum eDI_SUM id);
|
||||
unsigned int di_sum_get(unsigned int ch, enum eDI_SUM id);
|
||||
void di_sum_get_info(unsigned int ch, enum eDI_SUM id, char **name,
|
||||
unsigned int *pval);
|
||||
unsigned int di_sum_get_tab_size(void);
|
||||
bool di_sum_check(unsigned int ch, enum eDI_SUM id);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* cfg ctr top
|
||||
* bool
|
||||
**************************************/
|
||||
char *di_cfg_top_get_name(enum eDI_CFG_TOP_IDX idx);
|
||||
void di_cfg_top_get_info(unsigned int idx, char **name);
|
||||
void di_cfg_top_init_val(void);
|
||||
bool di_cfg_top_get(enum eDI_CFG_TOP_IDX id);
|
||||
void di_cfg_top_set(enum eDI_CFG_TOP_IDX id, bool en);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* cfg ctr x
|
||||
* bool
|
||||
**************************************/
|
||||
char *di_cfgx_get_name(enum eDI_CFGX_IDX idx);
|
||||
void di_cfgx_get_info(enum eDI_CFGX_IDX idx, char **name);
|
||||
void di_cfgx_init_val(void);
|
||||
bool di_cfgx_get(unsigned int ch, enum eDI_CFGX_IDX idx);
|
||||
void di_cfgx_set(unsigned int ch, enum eDI_CFGX_IDX idx, bool en);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* module para top
|
||||
* int
|
||||
**************************************/
|
||||
char *di_mp_uit_get_name(enum eDI_MP_UI_T idx);
|
||||
void di_mp_uit_init_val(void);
|
||||
int di_mp_uit_get(enum eDI_MP_UI_T idx);
|
||||
void di_mp_uit_set(enum eDI_MP_UI_T idx, int val);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* module para x
|
||||
* unsigned int
|
||||
**************************************/
|
||||
char *di_mp_uix_get_name(enum eDI_MP_UIX_T idx);
|
||||
void di_mp_uix_init_val(void);
|
||||
unsigned int di_mp_uix_get(unsigned int ch, enum eDI_MP_UIX_T idx);
|
||||
void di_mp_uix_set(unsigned int ch, enum eDI_MP_UIX_T idx,
|
||||
unsigned int val);
|
||||
|
||||
/****************************************/
|
||||
/* do_table */
|
||||
/****************************************/
|
||||
void do_table_init(struct do_table_s *pdo,
|
||||
const struct do_table_ops_s *ptable,
|
||||
unsigned int size_tab);
|
||||
/* now only call in same thread */
|
||||
void do_talbe_cmd(struct do_table_s *pdo, enum eDO_TABLE_CMD cmd);
|
||||
void do_table_working(struct do_table_s *pdo);
|
||||
bool do_table_is_crr(struct do_table_s *pdo, unsigned int state);
|
||||
|
||||
enum eDI_SUB_ID pw_ch_next_count(enum eDI_SUB_ID channel);
|
||||
|
||||
void dip_init_value_reg(unsigned int ch);
|
||||
|
||||
bool di_is_pause(unsigned int ch);
|
||||
void di_pause_step_done(unsigned int ch);
|
||||
void di_pause(unsigned int ch, bool on);
|
||||
|
||||
#endif /*__DI_PRC_H__*/
|
||||
985
drivers/amlogic/media/di_multi/di_pre.c
Normal file
985
drivers/amlogic/media/di_multi/di_pre.c
Normal file
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pre.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "deinterlace.h"
|
||||
#include "deinterlace_dbg.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_data.h"
|
||||
#include "di_dbg.h"
|
||||
#include "di_vframe.h"
|
||||
#include "di_que.h"
|
||||
#include "di_task.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
#include "di_pre.h"
|
||||
|
||||
#include "nr_downscale.h"
|
||||
#include "register.h"
|
||||
|
||||
/****************************************
|
||||
* 1. copy curr to last
|
||||
* 2. set curr
|
||||
****************************************/
|
||||
void pre_vinfo_set(unsigned int ch,
|
||||
struct vframe_s *ori_vframe)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
struct di_vinfo_s *vc = &pre->vinf_curr;
|
||||
struct di_vinfo_s *vl = &pre->vinf_lst;
|
||||
|
||||
memcpy(vl, vc, sizeof(struct di_vinfo_s));
|
||||
|
||||
vc->ch = ch;
|
||||
vc->vtype = ori_vframe->type;
|
||||
vc->src_type = ori_vframe->source_type;
|
||||
vc->trans_fmt = ori_vframe->trans_fmt;
|
||||
|
||||
if (COM_ME(ori_vframe->type, VIDTYPE_COMPRESS)) {
|
||||
vc->h = ori_vframe->compWidth;
|
||||
vc->v = ori_vframe->compHeight;
|
||||
} else {
|
||||
vc->h = ori_vframe->width;
|
||||
vc->v = ori_vframe->height;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* compare current vframe info with last
|
||||
* return
|
||||
* 0. no change
|
||||
* 1. video format channge
|
||||
* 2. scan mode channge?
|
||||
****************************************/
|
||||
unsigned int is_vinfo_change(unsigned int ch)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
struct di_vinfo_s *vc = &pre->vinf_curr;
|
||||
struct di_vinfo_s *vl = &pre->vinf_lst;
|
||||
struct di_pre_stru_s *ppre = get_pre_stru(ch);
|
||||
unsigned int ret = 0;
|
||||
|
||||
if (vc->src_type != vl->src_type ||
|
||||
!COM_M(DI_VFM_T_MASK_CHANGE, vc->vtype, vl->vtype) ||
|
||||
vc->v != vl->v ||
|
||||
vc->h != vl->h ||
|
||||
vc->trans_fmt != vl->trans_fmt) {
|
||||
/* video format changed */
|
||||
ret = 1;
|
||||
} else if (!COM_M(VIDTYPE_VIU_FIELD, vc->vtype, vl->vtype))
|
||||
/* just scan mode changed */
|
||||
ret = 2;
|
||||
|
||||
if (ret) {
|
||||
dim_print(
|
||||
"%s:ch[%d]: %dth source change 2: 0x%x/%d/%d/%d=>0x%x/%d/%d/%d\n",
|
||||
__func__,
|
||||
ch,
|
||||
/*jiffies_to_msecs(jiffies_64),*/
|
||||
ppre->in_seq,
|
||||
vl->vtype,
|
||||
vl->h,
|
||||
vl->v,
|
||||
vl->src_type,
|
||||
vc->vtype,
|
||||
vc->h,
|
||||
vc->v,
|
||||
vc->src_type);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (!vfm)
|
||||
return ret;
|
||||
pre_vinfo_set(ch, vfm);
|
||||
if (is_vinfo_change(ch)) {
|
||||
if (!is_bypass2(vfm, ch)) {
|
||||
set_bypass2_complete(ch, false);
|
||||
PR_INF("%s:\n", __func__);
|
||||
/*task_send_ready();*/
|
||||
task_send_cmd(LCMD1(eCMD_CHG, ch));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int di_get_other_ch(unsigned int curr)
|
||||
{
|
||||
return curr ? 0 : 1;
|
||||
}
|
||||
|
||||
bool is_bypass_i_p(void)
|
||||
{
|
||||
bool ret = false;
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
struct di_vinfo_s *vc = &pre->vinf_curr;
|
||||
#if 0
|
||||
struct di_vinfo_s *vl = &pre->vinf_lst;
|
||||
|
||||
if (vl->ch != vc->ch &&
|
||||
vf_type_is_interlace(vl->vtype) &&
|
||||
vf_type_is_prog(vc->vtype)) {
|
||||
ret = true;
|
||||
}
|
||||
#else
|
||||
unsigned int ch_c, ch_l;
|
||||
|
||||
struct di_pre_stru_s *ppre_c, *ppre_l;
|
||||
|
||||
if (!get_reg_flag(0) ||
|
||||
!get_reg_flag(1))
|
||||
return ret;
|
||||
|
||||
ch_c = vc->ch;
|
||||
ch_l = (ch_c ? 0 : 1);
|
||||
ppre_c = get_pre_stru(ch_c);
|
||||
ppre_l = get_pre_stru(ch_l);
|
||||
if (vf_type_is_interlace(ppre_l->cur_inp_type) &&
|
||||
vf_type_is_prog(ppre_c->cur_inp_type)) {
|
||||
ret = true;
|
||||
dim_print("ch[%d]:bypass p\n", ch_c);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpre_clear(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
memset(pre, 0, sizeof(struct di_hpre_s));
|
||||
}
|
||||
|
||||
void dpre_init(void)
|
||||
{/*reg:*/
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
pre->pre_st = eDI_PRE_ST_IDLE;
|
||||
|
||||
/*timer out*/
|
||||
di_tout_int(&pre->tout, 40); /*ms*/
|
||||
}
|
||||
|
||||
void pw_use_hw_pre(enum eDI_SUB_ID channel, bool on)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
pre->hw_flg_busy_pre = on;
|
||||
if (on)
|
||||
pre->curr_ch = channel;
|
||||
}
|
||||
|
||||
enum eDI_SUB_ID pw_ch_next_count(enum eDI_SUB_ID channel)
|
||||
{
|
||||
int i;
|
||||
unsigned int lch, nch;
|
||||
|
||||
nch = channel;
|
||||
for (i = 0; i < DI_CHANNEL_NUB; i++) {
|
||||
lch = channel + i + 1;
|
||||
if (lch >= DI_CHANNEL_NUB)
|
||||
lch -= DI_CHANNEL_NUB;
|
||||
#if 0
|
||||
if (pbm->sub_act_flg[lch]) {
|
||||
nch = lch;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (get_reg_flag(lch) &&
|
||||
!get_flag_trig_unreg(lch) &&
|
||||
!is_bypss2_complete(lch)) {
|
||||
nch = lch;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return nch;
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
static bool pw_try_sw_ch_next_pre(enum eDI_SUB_ID channel)
|
||||
{
|
||||
bool ret = false;
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
enum eDI_SUB_ID lst_ch, nch;
|
||||
|
||||
lst_ch = channel;
|
||||
|
||||
nch = pw_ch_next_count(lst_ch);
|
||||
if (!get_reg_flag(nch) ||
|
||||
get_flag_trig_unreg(nch) ||
|
||||
is_bypss2_complete(nch))
|
||||
return false;
|
||||
|
||||
pre->curr_ch = nch;
|
||||
pre->hw_flg_busy_pre = true;
|
||||
ret = true;
|
||||
|
||||
/*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* debug */
|
||||
/*****************************/
|
||||
|
||||
unsigned int di_dbg_pre_cnt;
|
||||
|
||||
void dbg_cnt_begin(void)
|
||||
{
|
||||
di_dbg_pre_cnt = 0x10;
|
||||
}
|
||||
|
||||
void dbg_cnt_print(void)
|
||||
{
|
||||
if (di_dbg_pre_cnt < 0xf)
|
||||
return;
|
||||
|
||||
if (di_dbg_pre_cnt > 0x10) {
|
||||
di_dbg_pre_cnt++;
|
||||
pr_info("di:[%d]\n", di_dbg_pre_cnt);
|
||||
}
|
||||
|
||||
if (di_dbg_pre_cnt > 0x15)
|
||||
di_dbg_pre_cnt = 0;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* STEP */
|
||||
/*****************************/
|
||||
void dpre_recyc(unsigned int ch)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
pre->check_recycle_buf_cnt = 0;
|
||||
while (dim_check_recycle_buf(ch) & 1) {
|
||||
if (pre->check_recycle_buf_cnt++ > MAX_IN_BUF_NUM) {
|
||||
di_pr_info("%s: dim_check_recycle_buf time out!!\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dpre_vdoing(unsigned int ch)
|
||||
{
|
||||
struct di_post_stru_s *ppost = get_post_stru(ch);
|
||||
|
||||
ppost->di_post_process_cnt = 0;
|
||||
while (dim_process_post_vframe(ch)) {
|
||||
if (ppost->di_post_process_cnt++ >
|
||||
MAX_POST_BUF_NUM) {
|
||||
di_pr_info("%s: dim_process_post_vframe time out!!\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool dpre_can_exit(unsigned int ch)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool ret = false;
|
||||
|
||||
if (ch != pre->curr_ch) {
|
||||
ret = true;
|
||||
} else {
|
||||
if (pre->pre_st <= eDI_PRE_ST4_IDLE)
|
||||
ret = true;
|
||||
}
|
||||
pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n",
|
||||
__func__,
|
||||
ch, pre->curr_ch,
|
||||
dpre_state4_name_get(pre->pre_st),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpre_dbg_f_trig(unsigned int cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
if (down_interruptible(&tsk->sem)) {
|
||||
PR_ERR("%s:can't get sem\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*set on/off and trig*/
|
||||
if (cmd & 0x10) {
|
||||
pre->dbg_f_en = 1;
|
||||
pre->dbg_f_cnt = cmd & 0xf;
|
||||
pre->dbg_f_lstate = pre->pre_st;
|
||||
} else {
|
||||
pre->dbg_f_en = 0;
|
||||
}
|
||||
|
||||
up(&tsk->sem);
|
||||
}
|
||||
|
||||
void dpre_process(void)
|
||||
{
|
||||
bool reflesh;
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
if (pre->dbg_f_en) {
|
||||
if (pre->dbg_f_cnt) {
|
||||
dpre_process_step4();
|
||||
pre->dbg_f_cnt--;
|
||||
}
|
||||
if (pre->dbg_f_lstate != pre->pre_st) {
|
||||
pr_info("ch[%d]:state:%s->%s\n",
|
||||
pre->curr_ch,
|
||||
dpre_state4_name_get(pre->dbg_f_lstate),
|
||||
dpre_state4_name_get(pre->pre_st));
|
||||
|
||||
pre->dbg_f_lstate = pre->pre_st;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
reflesh = true;
|
||||
|
||||
while (reflesh) {
|
||||
reflesh = dpre_process_step4();
|
||||
#if 0 /*debug only*/
|
||||
dbg_tsk("ch[%d]:st[%s]r[%d]\n", pre->curr_ch,
|
||||
dpre_state4_name_get(pre->pre_st), reflesh);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
enum eDI_PRE_MT {
|
||||
eDI_PRE_MT_CHECK = K_DO_TABLE_ID_START,
|
||||
eDI_PRE_MT_SET,
|
||||
eDI_PRE_MT_WAIT_INT,
|
||||
eDI_PRE_MT_TIME_OUT,
|
||||
};
|
||||
|
||||
/*use do_table:*/
|
||||
unsigned int dpre_mtotal_check(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
if ((pre_run_flag == DI_RUN_FLAG_RUN) ||
|
||||
(pre_run_flag == DI_RUN_FLAG_STEP)) {
|
||||
if (pre_run_flag == DI_RUN_FLAG_STEP)
|
||||
pre_run_flag = DI_RUN_FLAG_STEP_DONE;
|
||||
/*dim_print("%s:\n", __func__);*/
|
||||
if (dim_pre_de_buf_config(pre->curr_ch))
|
||||
ret = K_DO_R_FINISH;
|
||||
else
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
|
||||
dim_dbg_pre_cnt(pre->curr_ch, "x");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mtotal_set(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
ulong flags = 0;
|
||||
|
||||
/*dim_print("%s:\n", __func__);*/
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_pre_de_process(pre->curr_ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
/*begin to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_EN, &pre->tout);
|
||||
|
||||
return K_DO_R_FINISH;
|
||||
}
|
||||
|
||||
enum eDI_WAIT_INT {
|
||||
eDI_WAIT_INT_NEED_WAIT,
|
||||
eDI_WAIT_INT_HAVE_INT,
|
||||
eDI_WAIT_INT_TIME_OUT,
|
||||
};
|
||||
|
||||
/*
|
||||
*return: enum eDI_WAIT_INT
|
||||
*
|
||||
*/
|
||||
enum eDI_WAIT_INT di_pre_wait_int(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
ulong flags = 0;
|
||||
struct di_pre_stru_s *ppre;
|
||||
|
||||
enum eDI_WAIT_INT ret = eDI_WAIT_INT_NEED_WAIT;
|
||||
|
||||
if (pre->flg_int_done) {
|
||||
/*have INT done flg*/
|
||||
/*DI_INTR_CTRL[bit 0], NRWR_done, set by
|
||||
* hardware when NRWR is done,clear by write 1
|
||||
* by code;[bit 1]
|
||||
* MTNWR_done, set by hardware when MTNWR
|
||||
* is done, clear by write 1 by code;these two
|
||||
* bits have nothing to do with
|
||||
* DI_INTR_CTRL[16](NRW irq mask, 0 to enable
|
||||
* irq) and DI_INTR_CTRL[17]
|
||||
* (MTN irq mask, 0 to enable irq).two
|
||||
* interrupts are raised if both
|
||||
* DI_INTR_CTRL[16] and DI_INTR_CTRL[17] are 0
|
||||
*/
|
||||
#if 0
|
||||
data32 = Rd(DI_INTR_CTRL);
|
||||
if (((data32 & 0x1) &&
|
||||
((ppre->enable_mtnwr == 0) || (data32 & 0x2))) ||
|
||||
(ppre->pre_de_clear_flag == 2)) {
|
||||
dim_RDMA_WR(DI_INTR_CTRL, data32);
|
||||
}
|
||||
#endif
|
||||
di_pre_wait_irq_set(false);
|
||||
/*finish to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_FINISH, &pre->tout);
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
|
||||
dim_pre_de_done_buf_config(pre->curr_ch, false);
|
||||
|
||||
pre->flg_int_done = 0;
|
||||
|
||||
dpre_recyc(pre->curr_ch);
|
||||
dpre_vdoing(pre->curr_ch);
|
||||
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
|
||||
ppre = get_pre_stru(pre->curr_ch);
|
||||
#if 0
|
||||
if (ppre->field_count_for_cont == 1) {
|
||||
usleep_range(2000, 2001);
|
||||
pr_info("delay 1ms\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = eDI_WAIT_INT_HAVE_INT;
|
||||
|
||||
} else {
|
||||
/*check if timeout:*/
|
||||
if (di_tout_contr(eDI_TOUT_CONTR_CHECK, &pre->tout)) {
|
||||
di_pre_wait_irq_set(false);
|
||||
/*return K_DO_R_FINISH;*/
|
||||
ret = eDI_WAIT_INT_TIME_OUT;
|
||||
}
|
||||
}
|
||||
/*debug:*/
|
||||
if (dbg_first_cnt_pre)
|
||||
dbg_first_frame("ch[%d],w_int[%d]\n", pre->curr_ch, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mtotal_wait_int(void *data)
|
||||
{
|
||||
enum eDI_WAIT_INT wret;
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
wret = di_pre_wait_int(NULL);
|
||||
switch (wret) {
|
||||
case eDI_WAIT_INT_NEED_WAIT:
|
||||
ret = K_DO_R_NOT_FINISH;
|
||||
break;
|
||||
case eDI_WAIT_INT_HAVE_INT:
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
break;
|
||||
case eDI_WAIT_INT_TIME_OUT:
|
||||
ret = K_DO_R_FINISH;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpre_mtotal_timeout_contr(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
/*move from di_pre_trigger_work*/
|
||||
if (dimp_get(eDI_MP_di_dbg_mask) & 4)
|
||||
dim_dump_mif_size_state(pre->pres, pre->psts);
|
||||
|
||||
dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en));
|
||||
if (di_get_dts_nrds_en())
|
||||
dim_nr_ds_hw_ctrl(false);
|
||||
pre->pres->pre_de_irq_timeout_count++;
|
||||
|
||||
pre->pres->pre_de_busy = 0;
|
||||
pre->pres->pre_de_clear_flag = 2;
|
||||
if ((dimp_get(eDI_MP_di_dbg_mask) & 0x2)) {
|
||||
pr_info("DI:ch[%d]*****wait %d timeout 0x%x(%d ms)*****\n",
|
||||
pre->curr_ch,
|
||||
pre->pres->field_count_for_cont,
|
||||
Rd(DI_INTR_CTRL),
|
||||
(unsigned int)(cur_to_msecs() -
|
||||
pre->pres->irq_time[1]));
|
||||
}
|
||||
/*******************************/
|
||||
dim_pre_de_done_buf_config(pre->curr_ch, true);
|
||||
|
||||
dpre_recyc(pre->curr_ch);
|
||||
dpre_vdoing(pre->curr_ch);
|
||||
/*******************************/
|
||||
/*dpre_recyc(pre->curr_ch);*/
|
||||
}
|
||||
|
||||
unsigned int dpre_mtotal_timeout(void *data)
|
||||
{
|
||||
ulong flags = 0;
|
||||
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dpre_mtotal_timeout_contr();
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
|
||||
return K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
|
||||
const struct do_table_ops_s pr_mode_total[] = {
|
||||
/*fix*/
|
||||
[K_DO_TABLE_ID_PAUSE] = {
|
||||
.id = K_DO_TABLE_ID_PAUSE,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pause",
|
||||
},
|
||||
[K_DO_TABLE_ID_STOP] = {
|
||||
.id = K_DO_TABLE_ID_STOP,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "stop",
|
||||
},
|
||||
/******************/
|
||||
[K_DO_TABLE_ID_START] = { /*eDI_PRE_MT_CHECK*/
|
||||
.id = K_DO_TABLE_ID_START,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_check,
|
||||
.do_stop_op = NULL,
|
||||
.name = "start-check",
|
||||
},
|
||||
[eDI_PRE_MT_SET] = {
|
||||
.id = eDI_PRE_MT_SET,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_set,
|
||||
.do_stop_op = NULL,
|
||||
.name = "set",
|
||||
},
|
||||
[eDI_PRE_MT_WAIT_INT] = {
|
||||
.id = eDI_PRE_MT_WAIT_INT,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_wait_int,
|
||||
.do_stop_op = NULL,
|
||||
.name = "wait_int",
|
||||
},
|
||||
[eDI_PRE_MT_TIME_OUT] = {
|
||||
.id = eDI_PRE_MT_TIME_OUT,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_timeout,
|
||||
.do_stop_op = NULL,
|
||||
.name = "timeout",
|
||||
},
|
||||
};
|
||||
|
||||
/****************************
|
||||
*
|
||||
* mode for p
|
||||
*
|
||||
****************************/
|
||||
enum eDI_PRE_MP {
|
||||
eDI_PRE_MP_CHECK = K_DO_TABLE_ID_START,
|
||||
eDI_PRE_MP_SET,
|
||||
eDI_PRE_MP_WAIT_INT,
|
||||
eDI_PRE_MP_TIME_OUT,
|
||||
eDI_PRE_MP_CHECK2,
|
||||
eDI_PRE_MP_SET2,
|
||||
eDI_PRE_MP_WAIT_INT2,
|
||||
eDI_PRE_MP_TIME_OUT2,
|
||||
};
|
||||
|
||||
unsigned int dpre_mp_check(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
if ((pre_run_flag == DI_RUN_FLAG_RUN) ||
|
||||
(pre_run_flag == DI_RUN_FLAG_STEP)) {
|
||||
if (pre_run_flag == DI_RUN_FLAG_STEP)
|
||||
pre_run_flag = DI_RUN_FLAG_STEP_DONE;
|
||||
/*dim_print("%s:\n", __func__);*/
|
||||
if (dim_pre_de_buf_config(pre->curr_ch)) {
|
||||
/*pre->flg_wait_int = false;*/
|
||||
/*pre_p_asi_set_next(pre->curr_ch);*/
|
||||
ret = K_DO_R_FINISH;
|
||||
} else {
|
||||
/*pre->flg_wait_int = false;*/
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
dim_dbg_pre_cnt(pre->curr_ch, "x");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_check2(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
if (dim_pre_de_buf_config(pre->curr_ch)) {
|
||||
/*pre->flg_wait_int = false;*/
|
||||
ret = K_DO_R_FINISH;
|
||||
}
|
||||
#if 0
|
||||
else {
|
||||
PR_ERR("%s:not second?ch[%d]\n", __func__, pre->curr_ch);
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_wait_int(void *data)
|
||||
{
|
||||
enum eDI_WAIT_INT wret;
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
wret = di_pre_wait_int(NULL);
|
||||
switch (wret) {
|
||||
case eDI_WAIT_INT_NEED_WAIT:
|
||||
ret = K_DO_R_NOT_FINISH;
|
||||
break;
|
||||
case eDI_WAIT_INT_HAVE_INT:
|
||||
ret = K_DO_R_JUMP(eDI_PRE_MP_CHECK2);
|
||||
break;
|
||||
case eDI_WAIT_INT_TIME_OUT:
|
||||
ret = K_DO_R_FINISH;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_wait_int2(void *data)
|
||||
{
|
||||
enum eDI_WAIT_INT wret;
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
wret = di_pre_wait_int(NULL);
|
||||
switch (wret) {
|
||||
case eDI_WAIT_INT_NEED_WAIT:
|
||||
ret = K_DO_R_NOT_FINISH;
|
||||
break;
|
||||
case eDI_WAIT_INT_HAVE_INT:
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
break;
|
||||
case eDI_WAIT_INT_TIME_OUT:
|
||||
ret = K_DO_R_FINISH;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_timeout(void *data)
|
||||
{
|
||||
dpre_mtotal_timeout_contr();
|
||||
|
||||
return K_DO_R_FINISH;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_timeout2(void *data)
|
||||
{
|
||||
dpre_mtotal_timeout_contr();
|
||||
|
||||
return K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
|
||||
const struct do_table_ops_s pre_mode_proc[] = {
|
||||
/*fix*/
|
||||
[K_DO_TABLE_ID_PAUSE] = {
|
||||
.id = K_DO_TABLE_ID_PAUSE,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pause",
|
||||
},
|
||||
[K_DO_TABLE_ID_STOP] = {
|
||||
.id = K_DO_TABLE_ID_STOP,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "stop",
|
||||
},
|
||||
/******************/
|
||||
[K_DO_TABLE_ID_START] = { /*eDI_PRE_MP_CHECK*/
|
||||
.id = K_DO_TABLE_ID_START,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL,
|
||||
.do_op = dpre_mp_check,
|
||||
.do_stop_op = NULL,
|
||||
.name = "start-check",
|
||||
},
|
||||
[eDI_PRE_MP_SET] = {
|
||||
.id = eDI_PRE_MP_SET,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mtotal_set,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pset",
|
||||
},
|
||||
[eDI_PRE_MP_WAIT_INT] = {
|
||||
.id = eDI_PRE_MP_WAIT_INT,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_wait_int,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pwait_int",
|
||||
},
|
||||
[eDI_PRE_MP_TIME_OUT] = {
|
||||
.id = eDI_PRE_MP_TIME_OUT,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_timeout,
|
||||
.do_stop_op = NULL,
|
||||
.name = "ptimeout",
|
||||
},
|
||||
/******/
|
||||
[eDI_PRE_MP_CHECK2] = { /*eDI_PRE_MP_CHECK2*/
|
||||
.id = eDI_PRE_MP_CHECK2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_check2,
|
||||
.do_stop_op = NULL,
|
||||
.name = "start-check",
|
||||
},
|
||||
[eDI_PRE_MP_SET2] = {
|
||||
.id = eDI_PRE_MP_SET2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mtotal_set,
|
||||
.do_stop_op = NULL,
|
||||
.name = "psetp2",
|
||||
},
|
||||
[eDI_PRE_MP_WAIT_INT2] = {
|
||||
.id = eDI_PRE_MP_WAIT_INT2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_wait_int2,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pwait_int2",
|
||||
},
|
||||
[eDI_PRE_MP_TIME_OUT2] = {
|
||||
.id = eDI_PRE_MP_TIME_OUT2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_timeout2,
|
||||
.do_stop_op = NULL,
|
||||
.name = "ptimeout2",
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
void pre_mode_setting(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
if (pre->pre_st != eDI_PRE_ST4_DO_TABLE)
|
||||
return;
|
||||
|
||||
do_table_working(&pre->sdt_mode);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
enum eDI_WORK_MODE pre_cfg_count_mode(unsigned int ch, struct vframe_s *vframe)
|
||||
{
|
||||
enum eDI_WORK_MODE pmode;
|
||||
|
||||
if (is_bypass2(vframe, ch)) {
|
||||
pmode = eDI_WORK_MODE_bypass_all;
|
||||
return pmode;
|
||||
}
|
||||
|
||||
if (COM_ME(vframe->type, VIDTYPE_INTERLACE)) {
|
||||
/*interlace:*/
|
||||
pmode = eDI_WORK_MODE_i;
|
||||
return pmode;
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_prog_proc_config) & 0x10)
|
||||
pmode = eDI_WORK_MODE_p_as_p;
|
||||
else if (is_from_vdin(vframe))
|
||||
pmode = eDI_WORK_MODE_p_use_ibuf;
|
||||
else
|
||||
pmode = eDI_WORK_MODE_p_as_i;
|
||||
|
||||
return pmode;
|
||||
}
|
||||
|
||||
unsigned int dpre_check_mode(unsigned int ch)
|
||||
{
|
||||
struct vframe_s *vframe;
|
||||
unsigned int mode;
|
||||
|
||||
vframe = pw_vf_peek(ch);
|
||||
|
||||
if (!vframe)
|
||||
return eDI_WORK_MODE_NONE;
|
||||
mode = pre_cfg_count_mode(ch, vframe);/*eDI_WORK_MODE_all;*/
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
bool dpre_step4_idle(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool reflesh = false;
|
||||
unsigned int ch;
|
||||
|
||||
ch = pre->curr_ch;
|
||||
if (!pw_try_sw_ch_next_pre(ch))
|
||||
return false;
|
||||
|
||||
if (pre->idle_cnt >= DI_CHANNEL_NUB) {
|
||||
pre->idle_cnt = 0;
|
||||
return false;
|
||||
}
|
||||
pre->pres = get_pre_stru(pre->curr_ch);
|
||||
pre->psts = get_post_stru(pre->curr_ch);
|
||||
|
||||
/*state*/
|
||||
pre->pre_st++;/*tmp*/
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpre_step4_check(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool reflesh = false;
|
||||
unsigned int mode;
|
||||
|
||||
/*get vframe and select mode
|
||||
* now: fix use total table
|
||||
*/
|
||||
|
||||
mode = dpre_check_mode(pre->curr_ch);
|
||||
|
||||
if (mode == eDI_WORK_MODE_NONE) {
|
||||
pre->pre_st--;
|
||||
pre->idle_cnt++;
|
||||
return true;
|
||||
}
|
||||
pre->idle_cnt = 0;
|
||||
if (mode == eDI_WORK_MODE_p_as_i) {
|
||||
do_table_init(&pre->sdt_mode,
|
||||
&pre_mode_proc[0],
|
||||
ARRAY_SIZE(pre_mode_proc));
|
||||
|
||||
} else {
|
||||
do_table_init(&pre->sdt_mode,
|
||||
&pr_mode_total[0],
|
||||
ARRAY_SIZE(pr_mode_total));
|
||||
}
|
||||
do_talbe_cmd(&pre->sdt_mode, eDO_TABLE_CMD_START);
|
||||
|
||||
/*state*/
|
||||
pre->pre_st++;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpre_step4_do_table(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool reflesh = false;
|
||||
|
||||
if (do_table_is_crr(&pre->sdt_mode, K_DO_TABLE_ID_STOP)) {
|
||||
pre->pre_st = eDI_PRE_ST4_IDLE;
|
||||
reflesh = true;
|
||||
}
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
const struct di_func_tab_s di_pre_func_tab4[] = {
|
||||
{eDI_PRE_ST4_EXIT, NULL},
|
||||
{eDI_PRE_ST4_IDLE, dpre_step4_idle},
|
||||
{eDI_PRE_ST4_CHECK, dpre_step4_check},
|
||||
{eDI_PRE_ST4_DO_TABLE, dpre_step4_do_table},
|
||||
};
|
||||
|
||||
const char * const dpre_state_name4[] = {
|
||||
"EXIT",
|
||||
"IDLE", /*swith to next channel?*/
|
||||
"CHECK",
|
||||
"DO_TABLE",
|
||||
};
|
||||
|
||||
const char *dpre_state4_name_get(enum eDI_PRE_ST4 state)
|
||||
{
|
||||
if (state > eDI_PRE_ST4_DO_TABLE)
|
||||
return "nothing";
|
||||
|
||||
return dpre_state_name4[state];
|
||||
}
|
||||
|
||||
bool dpre_process_step4(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
enum eDI_PRE_ST4 pre_st = pre->pre_st;
|
||||
ulong flags = 0;
|
||||
|
||||
if (pre_st > eDI_PRE_ST4_EXIT) {
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_recycle_post_back(pre->curr_ch);
|
||||
dpre_recyc(pre->curr_ch);
|
||||
dpre_vdoing(pre->curr_ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
}
|
||||
if ((pre_st <= eDI_PRE_ST4_DO_TABLE) &&
|
||||
di_pre_func_tab4[pre_st].func) {
|
||||
return di_pre_func_tab4[pre_st].func();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
38
drivers/amlogic/media/di_multi/di_pre.h
Normal file
38
drivers/amlogic/media/di_multi/di_pre.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pre.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_PRE_H__
|
||||
#define __DI_PRE_H__
|
||||
|
||||
void dpre_process(void);
|
||||
|
||||
void dpre_init(void);
|
||||
|
||||
const char *dpre_state_name_get(enum eDI_PRE_ST state);
|
||||
void dpre_dbg_f_trig(unsigned int cmd);
|
||||
void pre_vinfo_set(unsigned int ch,
|
||||
struct vframe_s *ori_vframe);
|
||||
unsigned int is_vinfo_change(unsigned int ch);
|
||||
bool dpre_can_exit(unsigned int ch);
|
||||
bool is_bypass_i_p(void);
|
||||
bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm);
|
||||
|
||||
void pre_mode_setting(void);
|
||||
bool dpre_process_step4(void);
|
||||
const char *dpre_state4_name_get(enum eDI_PRE_ST4 state);
|
||||
|
||||
#endif /*__DI_PRE_H__*/
|
||||
995
drivers/amlogic/media/di_multi/di_que.c
Normal file
995
drivers/amlogic/media/di_multi/di_que.c
Normal file
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_que.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "deinterlace.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_que.h"
|
||||
#include "di_vframe.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
|
||||
const char * const di_name_new_que[QUE_NUB] = {
|
||||
"QUE_IN_FREE", /*0*/
|
||||
"QUE_PRE_READY", /*1*/
|
||||
"QUE_POST_FREE", /*2*/
|
||||
"QUE_POST_READY", /*3*/
|
||||
"QUE_POST_BACK", /*4*/
|
||||
"QUE_DBG",
|
||||
/* "QUE_NUB",*/
|
||||
|
||||
};
|
||||
|
||||
#define que_dbg dim_print
|
||||
|
||||
static void pw_queue_clear(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return;
|
||||
#endif
|
||||
kfifo_reset(&pch->fifo[qtype]);
|
||||
}
|
||||
|
||||
bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype, unsigned int buf_index)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
if (kfifo_in(&pch->fifo[qtype], &buf_index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
#if 0
|
||||
|
||||
/*below for debug: save in que*/
|
||||
if (qtype <= QUE_POST_RECYC) {
|
||||
if (buf_index >= MAX_POST_BUF_NUM) {
|
||||
pr_err("%s:err:overflow?[%d]\n", __func__, buf_index);
|
||||
} else {
|
||||
ppw = &pch->lpost_buf[buf_index];
|
||||
ppw->in_qtype = qtype;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *buf_index)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int index;
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
if (kfifo_out(&pch->fifo[qtype], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
|
||||
*buf_index = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pw_queue_peek(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *buf_index)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int index;
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (kfifo_out_peek(&pch->fifo[qtype], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
|
||||
*buf_index = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pw_queue_move(unsigned int ch, enum QUE_TYPE qtypef, enum QUE_TYPE qtypet,
|
||||
unsigned int *oindex)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int index;
|
||||
|
||||
/*struct di_post_buf_s *ppw;*/ /*debug only*/
|
||||
|
||||
#if 0
|
||||
if (qtypef >= QUE_NUB || qtypet >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
if (kfifo_out(&pch->fifo[qtypef], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int)) {
|
||||
PR_ERR("qtypef[%d] is empty\n", qtypef);
|
||||
return false;
|
||||
}
|
||||
if (kfifo_in(&pch->fifo[qtypet], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int)) {
|
||||
PR_ERR("qtypet[%d] is full\n", qtypet);
|
||||
return false;
|
||||
}
|
||||
|
||||
*oindex = index;
|
||||
#if 0
|
||||
if (qtypet <= QUE_POST_RECYC) {
|
||||
/*below for debug: save in que*/
|
||||
if (index >= MAX_POST_BUF_NUM) {
|
||||
pr_err("%s:err:overflow?[%d]\n", __func__, index);
|
||||
} else {
|
||||
ppw = &pch->lpost_buf[index];
|
||||
ppw->in_qtype = qtypet;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
if (kfifo_is_empty(&pch->fifo[qtype]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int length;
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return -1;
|
||||
#endif
|
||||
length = kfifo_len(&pch->fifo[qtype]);
|
||||
length = length / sizeof(unsigned int);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
/*outbuf : array size MAX_FIFO_SIZE*/
|
||||
/***************************************/
|
||||
bool di_que_list(unsigned int ch, enum QUE_TYPE qtype, unsigned int *outbuf,
|
||||
unsigned int *rsize)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
/* unsigned int tmp[MAX_FIFO_SIZE + 1];*/
|
||||
int i;
|
||||
unsigned int index;
|
||||
bool ret = false;
|
||||
|
||||
/*que_dbg("%s:begin\n", __func__);*/
|
||||
for (i = 0; i < MAX_FIFO_SIZE; i++)
|
||||
outbuf[i] = 0xff;
|
||||
|
||||
if (kfifo_is_empty(&pch->fifo[qtype])) {
|
||||
que_dbg("\t%d:empty\n", qtype);
|
||||
*rsize = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
memcpy(&pch->fifo[QUE_DBG], &pch->fifo[qtype],
|
||||
sizeof(pch->fifo[qtype]));
|
||||
|
||||
#if 0
|
||||
if (kfifo_is_empty(&pbm->fifo[QUE_DBG]))
|
||||
pr_err("%s:err, kfifo can not copy?\n", __func__);
|
||||
|
||||
#endif
|
||||
i = 0;
|
||||
*rsize = 0;
|
||||
|
||||
while (kfifo_out(&pch->fifo[QUE_DBG], &index, sizeof(unsigned int))
|
||||
== sizeof(unsigned int)) {
|
||||
outbuf[i] = index;
|
||||
/*pr_info("%d->%d\n",i,index);*/
|
||||
i++;
|
||||
}
|
||||
*rsize = di_que_list_count(ch, qtype);
|
||||
#if 0 /*debug only*/
|
||||
que_dbg("%s: size[%d]\n", di_name_new_que[qtype], *rsize);
|
||||
for (i = 0; i < *rsize; i++)
|
||||
que_dbg("%d,", outbuf[i]);
|
||||
|
||||
que_dbg("\n");
|
||||
#endif
|
||||
/*que_dbg("finish\n");*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int di_que_is_empty(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return -1;
|
||||
#endif
|
||||
return kfifo_is_empty(&pch->fifo[qtype]);
|
||||
}
|
||||
|
||||
void di_que_init(unsigned int ch)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < QUE_NUB; i++)
|
||||
pw_queue_clear(ch, i);
|
||||
}
|
||||
|
||||
bool di_que_alloc(unsigned int ch)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
bool flg_err;
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
/*kfifo----------------------------*/
|
||||
flg_err = 0;
|
||||
for (i = 0; i < QUE_NUB; i++) {
|
||||
ret = kfifo_alloc(&pch->fifo[i],
|
||||
sizeof(unsigned int) * MAX_FIFO_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
flg_err = 1;
|
||||
PR_ERR("%s:%d:can't get kfifo\n", __func__, i);
|
||||
break;
|
||||
}
|
||||
pch->flg_fifo[i] = 1;
|
||||
}
|
||||
#if 0
|
||||
/*canvas-----------------------------*/
|
||||
canvas_alloc();
|
||||
#endif
|
||||
/* pdp_clear();*/
|
||||
|
||||
if (!flg_err) {
|
||||
/*pbm->flg_fifo = 1;*/
|
||||
pr_info("%s:ok\n", __func__);
|
||||
ret = true;
|
||||
} else {
|
||||
di_que_release(ch);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void di_que_release(unsigned int ch)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
int i;
|
||||
|
||||
/* canvas_release();*/
|
||||
for (i = 0; i < QUE_NUB; i++) {
|
||||
if (pch->flg_fifo[i]) {
|
||||
kfifo_free(&pch->fifo[i]);
|
||||
pch->flg_fifo[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("%s:ok\n", __func__);
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*get di_buf from index that same in que
|
||||
* (di_buf->type << 8) | (di_buf->index)
|
||||
********************************************/
|
||||
struct di_buf_s *pw_qindex_2_buf(unsigned int ch, unsigned int qindex)
|
||||
{
|
||||
union uDI_QBUF_INDEX index;
|
||||
struct di_buf_s *di_buf;
|
||||
struct di_buf_pool_s *pbuf_pool = get_buf_pool(ch);
|
||||
|
||||
index.d32 = qindex;
|
||||
di_buf = &pbuf_pool[index.b.type - 1].di_buf_ptr[index.b.index];
|
||||
|
||||
return di_buf;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/*get di_buf from index that same in que*/
|
||||
/*(di_buf->type << 8) | (di_buf->index)*/
|
||||
/********************************************/
|
||||
static unsigned int pw_buf_2_qindex(unsigned int ch, struct di_buf_s *pdi_buf)
|
||||
{
|
||||
union uDI_QBUF_INDEX index;
|
||||
|
||||
index.b.index = pdi_buf->index;
|
||||
index.b.type = pdi_buf->type;
|
||||
return index.d32;
|
||||
}
|
||||
|
||||
/*di_buf is out*/
|
||||
struct di_buf_s *di_que_out_to_di_buf(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
unsigned int q_index;
|
||||
struct di_buf_s *pdi_buf = NULL;
|
||||
|
||||
if (!pw_queue_peek(ch, qtype, &q_index))
|
||||
return pdi_buf;
|
||||
|
||||
pdi_buf = pw_qindex_2_buf(ch, q_index);
|
||||
if (!pdi_buf) {
|
||||
PR_ERR("di:err:%s:buf is null[%d]\n", __func__, q_index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pw_queue_out(ch, qtype, &q_index);
|
||||
pdi_buf->queue_index = -1;
|
||||
|
||||
return pdi_buf;
|
||||
}
|
||||
|
||||
/*di_buf is input*/
|
||||
bool di_que_out(unsigned int ch, enum QUE_TYPE qtype, struct di_buf_s *di_buf)
|
||||
{
|
||||
unsigned int q_index;
|
||||
unsigned int q_index2;
|
||||
|
||||
if (!pw_queue_peek(ch, qtype, &q_index))
|
||||
return false;
|
||||
|
||||
q_index2 = pw_buf_2_qindex(ch, di_buf);
|
||||
if (q_index2 != q_index) {
|
||||
PR_ERR("di:%s:not map[%d,%d]\n", __func__, q_index2, q_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
pw_queue_out(ch, qtype, &q_index);
|
||||
di_buf->queue_index = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool di_que_in(unsigned int ch, enum QUE_TYPE qtype, struct di_buf_s *di_buf)
|
||||
{
|
||||
unsigned int q_index;
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("di:%s:err:di_buf is NULL,ch[%d],qtype[%d]\n",
|
||||
__func__, ch, qtype);
|
||||
return false;
|
||||
}
|
||||
if (di_buf->queue_index != -1) {
|
||||
PR_ERR("di:%s:buf in some que,ch[%d],qt[%d],qi[%d],bi[%d]\n",
|
||||
__func__,
|
||||
ch, qtype, di_buf->queue_index, di_buf->index);
|
||||
return false;
|
||||
}
|
||||
|
||||
q_index = pw_buf_2_qindex(ch, di_buf);
|
||||
|
||||
if (!pw_queue_in(ch, qtype, q_index)) {
|
||||
PR_ERR("di:%s:err:can't que in,ch[%d],qtype[%d],q_index[%d]\n",
|
||||
__func__,
|
||||
ch, qtype, q_index);
|
||||
return false;
|
||||
}
|
||||
di_buf->queue_index = qtype + QUEUE_NUM;
|
||||
|
||||
if (qtype == QUE_PRE_READY)
|
||||
dim_print("di:pre_ready in %d\n", di_buf->index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf)
|
||||
{
|
||||
unsigned int q_index;
|
||||
unsigned int arr[MAX_FIFO_SIZE + 1];
|
||||
unsigned int asize = 0;
|
||||
bool ret = false;
|
||||
unsigned int i;
|
||||
|
||||
if (!di_buf)
|
||||
return false;
|
||||
|
||||
q_index = pw_buf_2_qindex(ch, di_buf);
|
||||
|
||||
di_que_list(ch, qtype, &arr[0], &asize);
|
||||
|
||||
if (asize == 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < asize; i++) {
|
||||
if (arr[i] == q_index) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*same as get_di_buf_head*/
|
||||
struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_buf_s *di_buf = NULL;
|
||||
unsigned int q_index;
|
||||
|
||||
if (!pw_queue_peek(ch, qtype, &q_index))
|
||||
return di_buf;
|
||||
di_buf = pw_qindex_2_buf(ch, q_index);
|
||||
|
||||
return di_buf;
|
||||
}
|
||||
|
||||
bool di_que_type_2_new(unsigned int q_type, enum QUE_TYPE *nqtype)
|
||||
{
|
||||
if (!F_IN(q_type, QUEUE_NEW_THD_MIN, QUEUE_NEW_THD_MAX))
|
||||
return false;
|
||||
*nqtype = (enum QUE_TYPE)(q_type - QUEUE_NUM);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
/**********************************************************/
|
||||
/*ary add this function for reg ini value, no need wait peek*/
|
||||
void queue_init2(unsigned int channel)
|
||||
{
|
||||
int i, j;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
|
||||
for (i = 0; i < QUEUE_NUM; i++) {
|
||||
queue_t *q = &pqueue[i];
|
||||
|
||||
for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++)
|
||||
q->pool[j] = 0;
|
||||
|
||||
q->in_idx = 0;
|
||||
q->out_idx = 0;
|
||||
q->num = 0;
|
||||
q->type = 0;
|
||||
if ((i == QUEUE_RECYCLE) ||
|
||||
(i == QUEUE_DISPLAY) ||
|
||||
(i == QUEUE_TMP) ||
|
||||
(i == QUEUE_POST_DOING))
|
||||
q->type = 1;
|
||||
|
||||
#if 0
|
||||
if ((i == QUEUE_LOCAL_FREE) && dim_get_use_2_int_buf())
|
||||
q->type = 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void queue_init(unsigned int channel, int local_buffer_num)
|
||||
{
|
||||
int i, j;
|
||||
struct di_buf_s *pbuf_local = get_buf_local(channel);
|
||||
struct di_buf_s *pbuf_in = get_buf_in(channel);
|
||||
struct di_buf_s *pbuf_post = get_buf_post(channel);
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel);
|
||||
|
||||
for (i = 0; i < QUEUE_NUM; i++) {
|
||||
queue_t *q = &pqueue[i];
|
||||
|
||||
for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++)
|
||||
q->pool[j] = 0;
|
||||
|
||||
q->in_idx = 0;
|
||||
q->out_idx = 0;
|
||||
q->num = 0;
|
||||
q->type = 0;
|
||||
if ((i == QUEUE_RECYCLE) ||
|
||||
(i == QUEUE_DISPLAY) ||
|
||||
(i == QUEUE_TMP)
|
||||
/*||(i == QUEUE_POST_DOING)*/
|
||||
)
|
||||
q->type = 1;
|
||||
|
||||
if ((i == QUEUE_LOCAL_FREE) &&
|
||||
dimp_get(eDI_MP_use_2_interlace_buff))
|
||||
q->type = 2;
|
||||
}
|
||||
if (local_buffer_num > 0) {
|
||||
pbuf_pool[VFRAME_TYPE_IN - 1].di_buf_ptr = &pbuf_in[0];
|
||||
pbuf_pool[VFRAME_TYPE_IN - 1].size = MAX_IN_BUF_NUM;
|
||||
|
||||
pbuf_pool[VFRAME_TYPE_LOCAL - 1].di_buf_ptr = &pbuf_local[0];
|
||||
pbuf_pool[VFRAME_TYPE_LOCAL - 1].size = local_buffer_num;
|
||||
|
||||
pbuf_pool[VFRAME_TYPE_POST - 1].di_buf_ptr = &pbuf_post[0];
|
||||
pbuf_pool[VFRAME_TYPE_POST - 1].size = MAX_POST_BUF_NUM;
|
||||
}
|
||||
}
|
||||
|
||||
struct di_buf_s *get_di_buf_head(unsigned int channel, int queue_idx)
|
||||
{
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
queue_t *q = &pqueue[queue_idx];
|
||||
int idx;
|
||||
unsigned int pool_idx, di_buf_idx;
|
||||
struct di_buf_s *di_buf = NULL;
|
||||
struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d>\n", __func__, queue_idx,
|
||||
q->num, q->in_idx, q->out_idx);
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype))
|
||||
return di_que_peek(channel, nqtype);
|
||||
|
||||
/* **************** */
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
idx = q->out_idx;
|
||||
} else {
|
||||
for (idx = 0; idx < MAX_QUEUE_POOL_SIZE; idx++)
|
||||
if (q->pool[idx] != 0)
|
||||
break;
|
||||
}
|
||||
if (idx < MAX_QUEUE_POOL_SIZE) {
|
||||
pool_idx = ((q->pool[idx] >> 8) & 0xff) - 1;
|
||||
di_buf_idx = q->pool[idx] & 0xff;
|
||||
|
||||
if (pool_idx < VFRAME_TYPE_NUM) {
|
||||
if (di_buf_idx < pbuf_pool[pool_idx].size)
|
||||
di_buf = &pbuf_pool[pool_idx].di_buf_ptr[di_buf_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((di_buf) && ((((pool_idx + 1) << 8) | di_buf_idx) !=
|
||||
((di_buf->type << 8) | (di_buf->index)))) {
|
||||
pr_dbg("%s: Error (%x,%x)\n", __func__,
|
||||
(((pool_idx + 1) << 8) | di_buf_idx),
|
||||
((di_buf->type << 8) | (di_buf->index)));
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(2);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
di_buf = NULL;
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) {
|
||||
if (di_buf)
|
||||
dim_print("%s: %x(%d,%d)\n", __func__, di_buf,
|
||||
pool_idx, di_buf_idx);
|
||||
else
|
||||
dim_print("%s: %x\n", __func__, di_buf);
|
||||
}
|
||||
|
||||
return di_buf;
|
||||
}
|
||||
|
||||
/*ary: note:*/
|
||||
/*a. di_buf->queue_index = -1*/
|
||||
/*b. */
|
||||
void queue_out(unsigned int channel, struct di_buf_s *di_buf)
|
||||
{
|
||||
int i;
|
||||
queue_t *q;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("%s:Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0)
|
||||
dim_vcry_set_log_reason(3);
|
||||
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(di_buf->queue_index, &nqtype)) {
|
||||
di_que_out(channel, nqtype, di_buf); /*?*/
|
||||
return;
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
if (di_buf->queue_index >= 0 && di_buf->queue_index < QUEUE_NUM) {
|
||||
q = &pqueue[di_buf->queue_index];
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d> %x\n", __func__,
|
||||
di_buf->queue_index, q->num, q->in_idx,
|
||||
q->out_idx, di_buf);
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
if (q->pool[q->out_idx] ==
|
||||
((di_buf->type << 8) | (di_buf->index))) {
|
||||
q->num--;
|
||||
q->pool[q->out_idx] = 0;
|
||||
q->out_idx++;
|
||||
if (q->out_idx >= MAX_QUEUE_POOL_SIZE)
|
||||
q->out_idx = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR(
|
||||
"%s: Error (%d, %x,%x)\n",
|
||||
__func__,
|
||||
di_buf->queue_index,
|
||||
q->pool[q->out_idx],
|
||||
((di_buf->type << 8) |
|
||||
(di_buf->index)));
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(4);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 1) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) {
|
||||
if (q->pool[i] == pool_val) {
|
||||
q->num--;
|
||||
q->pool[i] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_QUEUE_POOL_SIZE) {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(5);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 2) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
if ((di_buf->index < MAX_QUEUE_POOL_SIZE) &&
|
||||
(q->pool[di_buf->index] == pool_val)) {
|
||||
q->num--;
|
||||
q->pool[di_buf->index] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(5);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PR_ERR("%s: Error, queue_index %d is not right\n",
|
||||
__func__, di_buf->queue_index);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(6);
|
||||
dim_vcry_set_log_q_idx(0);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s done\n", __func__);
|
||||
}
|
||||
|
||||
void queue_out_dbg(unsigned int channel, struct di_buf_s *di_buf)
|
||||
{
|
||||
int i;
|
||||
queue_t *q;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("%s:Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0)
|
||||
dim_vcry_set_log_reason(3);
|
||||
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(di_buf->queue_index, &nqtype)) {
|
||||
di_que_out(channel, nqtype, di_buf); /*?*/
|
||||
pr_info("dbg1:nqtype=%d\n", nqtype);
|
||||
return;
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
if (di_buf->queue_index >= 0 && di_buf->queue_index < QUEUE_NUM) {
|
||||
q = &pqueue[di_buf->queue_index];
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d> %x\n", __func__,
|
||||
di_buf->queue_index, q->num, q->in_idx,
|
||||
q->out_idx, di_buf);
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
pr_info("dbg3\n");
|
||||
if (q->pool[q->out_idx] ==
|
||||
((di_buf->type << 8) | (di_buf->index))) {
|
||||
q->num--;
|
||||
q->pool[q->out_idx] = 0;
|
||||
q->out_idx++;
|
||||
if (q->out_idx >= MAX_QUEUE_POOL_SIZE)
|
||||
q->out_idx = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR(
|
||||
"%s: Error (%d, %x,%x)\n",
|
||||
__func__,
|
||||
di_buf->queue_index,
|
||||
q->pool[q->out_idx],
|
||||
((di_buf->type << 8) |
|
||||
(di_buf->index)));
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(4);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 1) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) {
|
||||
if (q->pool[i] == pool_val) {
|
||||
q->num--;
|
||||
q->pool[i] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pr_info("dbg2:i=%d,qindex=%d\n", i,
|
||||
di_buf->queue_index);
|
||||
if (i == MAX_QUEUE_POOL_SIZE) {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(5);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 2) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
|
||||
pr_info("dbg4\n");
|
||||
if ((di_buf->index < MAX_QUEUE_POOL_SIZE) &&
|
||||
(q->pool[di_buf->index] == pool_val)) {
|
||||
q->num--;
|
||||
q->pool[di_buf->index] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set(5,
|
||||
di_buf->queue_index,
|
||||
di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PR_ERR("%s: Error, queue_index %d is not right\n",
|
||||
__func__, di_buf->queue_index);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(6);
|
||||
dim_vcry_set_log_q_idx(0);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s done\n", __func__);
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
/* set di_buf->queue_index*/
|
||||
/***************************************/
|
||||
void queue_in(unsigned int channel, struct di_buf_s *di_buf, int queue_idx)
|
||||
{
|
||||
queue_t *q = NULL;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("%s:Error\n", __func__);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(7);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype)) {
|
||||
di_que_in(channel, nqtype, di_buf);
|
||||
return;
|
||||
}
|
||||
/* **************** */
|
||||
if (di_buf->queue_index != -1) {
|
||||
PR_ERR("%s:%s[%d] queue_index(%d) is not -1, to que[%d]\n",
|
||||
__func__, dim_get_vfm_type_name(di_buf->type),
|
||||
di_buf->index, di_buf->queue_index, queue_idx);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(8);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
q = &pqueue[queue_idx];
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d> %x\n", __func__, queue_idx,
|
||||
q->num, q->in_idx, q->out_idx, di_buf);
|
||||
|
||||
if (q->type == 0) {
|
||||
q->pool[q->in_idx] = (di_buf->type << 8) | (di_buf->index);
|
||||
di_buf->queue_index = queue_idx;
|
||||
q->in_idx++;
|
||||
if (q->in_idx >= MAX_QUEUE_POOL_SIZE)
|
||||
q->in_idx = 0;
|
||||
|
||||
q->num++;
|
||||
} else if (q->type == 1) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) {
|
||||
if (q->pool[i] == 0) {
|
||||
q->pool[i] =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
di_buf->queue_index = queue_idx;
|
||||
q->num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_QUEUE_POOL_SIZE) {
|
||||
pr_dbg("%s: Error\n", __func__);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(9);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 2) {
|
||||
if ((di_buf->index < MAX_QUEUE_POOL_SIZE) &&
|
||||
(q->pool[di_buf->index] == 0)) {
|
||||
q->pool[di_buf->index] =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
di_buf->queue_index = queue_idx;
|
||||
q->num++;
|
||||
} else {
|
||||
pr_dbg("%s: Error\n", __func__);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(9);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s done\n", __func__);
|
||||
}
|
||||
|
||||
int list_count(unsigned int channel, int queue_idx)
|
||||
{
|
||||
struct queue_s *pqueue;
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype)) {
|
||||
PR_ERR("%s:err: over flow\n", __func__);
|
||||
return di_que_list_count(channel, nqtype);
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
pqueue = get_queue(channel);
|
||||
return pqueue[queue_idx].num;
|
||||
}
|
||||
|
||||
bool queue_empty(unsigned int channel, int queue_idx)
|
||||
{
|
||||
struct queue_s *pqueue;
|
||||
bool ret;
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype)) {
|
||||
PR_ERR("%s:err: over flow\n", __func__);
|
||||
return di_que_is_empty(channel, nqtype);
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
pqueue = get_queue(channel);
|
||||
ret = (pqueue[queue_idx].num == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool is_in_queue(unsigned int channel, struct di_buf_s *di_buf, int queue_idx)
|
||||
{
|
||||
bool ret = 0;
|
||||
struct di_buf_s *p = NULL;
|
||||
int itmp;
|
||||
unsigned int overflow_cnt;
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype))
|
||||
return di_que_is_in_que(channel, nqtype, di_buf);
|
||||
|
||||
/* **************** */
|
||||
|
||||
overflow_cnt = 0;
|
||||
if (!di_buf || (queue_idx < 0) || (queue_idx >= QUEUE_NUM)) {
|
||||
ret = 0;
|
||||
dim_print("%s: not in queue:%d!!!\n", __func__, queue_idx);
|
||||
return ret;
|
||||
}
|
||||
queue_for_each_entry(p, channel, queue_idx, list) {
|
||||
if (p == di_buf) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
if (overflow_cnt++ > MAX_QUEUE_POOL_SIZE) {
|
||||
ret = 0;
|
||||
dim_print("%s: overflow_cnt!!!\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
76
drivers/amlogic/media/di_multi/di_que.h
Normal file
76
drivers/amlogic/media/di_multi/di_que.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_que.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_QUE_H__
|
||||
#define __DI_QUE_H__
|
||||
|
||||
void queue_init(unsigned int channel, int local_buffer_num);
|
||||
void queue_out(unsigned int channel, struct di_buf_s *di_buf);
|
||||
void queue_in(unsigned int channel, struct di_buf_s *di_buf,
|
||||
int queue_idx);
|
||||
int list_count(unsigned int channel, int queue_idx);
|
||||
bool queue_empty(unsigned int channel, int queue_idx);
|
||||
bool is_in_queue(unsigned int channel, struct di_buf_s *di_buf,
|
||||
int queue_idx);
|
||||
struct di_buf_s *get_di_buf_head(unsigned int channel,
|
||||
int queue_idx);
|
||||
|
||||
void queue_init2(unsigned int channel);
|
||||
|
||||
/*new buf:*/
|
||||
bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int buf_index);
|
||||
bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *buf_index);
|
||||
bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype);
|
||||
|
||||
/******************************************/
|
||||
/*new api*/
|
||||
/******************************************/
|
||||
union uDI_QBUF_INDEX {
|
||||
unsigned int d32;
|
||||
struct {
|
||||
unsigned int index:8, /*low*/
|
||||
type:8,
|
||||
reserved0:16;
|
||||
} b;
|
||||
};
|
||||
|
||||
void di_que_init(unsigned int ch);
|
||||
bool di_que_alloc(unsigned int ch);
|
||||
void di_que_release(unsigned int ch);
|
||||
|
||||
int di_que_is_empty(unsigned int ch, enum QUE_TYPE qtype);
|
||||
bool di_que_out(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf);
|
||||
|
||||
struct di_buf_s *di_que_out_to_di_buf(unsigned int ch,
|
||||
enum QUE_TYPE qtype);
|
||||
bool di_que_in(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf);
|
||||
bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf);
|
||||
struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype);
|
||||
bool di_que_type_2_new(unsigned int q_type, enum QUE_TYPE *nqtype);
|
||||
int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype);
|
||||
bool di_que_list(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *outbuf, unsigned int *rsize);
|
||||
|
||||
struct di_buf_s *pw_qindex_2_buf(unsigned int ch, unsigned int qindex);
|
||||
|
||||
void queue_out_dbg(unsigned int channel, struct di_buf_s *di_buf);
|
||||
#endif /*__DI_QUE_H__*/
|
||||
249
drivers/amlogic/media/di_multi/di_reg_tab.c
Normal file
249
drivers/amlogic/media/di_multi/di_reg_tab.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_reg_tab.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/amlogic/iomap.h>
|
||||
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
#include "register.h"
|
||||
|
||||
static const struct reg_t rtab_contr[] = {
|
||||
/*--------------------------*/
|
||||
{VD1_AFBCD0_MISC_CTRL, 20, 2, 0, "VD1_AFBCD0_MISC_CTRL",
|
||||
"vd1_go_field_sel",
|
||||
"0: gofile;1: post;2: pre"},
|
||||
{VD1_AFBCD0_MISC_CTRL, 9, 1, 0, "",
|
||||
"afbc0_mux_vpp_mad",
|
||||
"afbc0 to 0:vpp; 1:di"},
|
||||
{VD1_AFBCD0_MISC_CTRL, 8, 1, 0, "",
|
||||
"di_mif0_en",
|
||||
":mif to 0-vpp;1-di"},
|
||||
/*--------------------------*/
|
||||
{DI_POST_CTRL, 12, 1, 0, "DI_POST_CTRL",
|
||||
"di_post_viu_link",
|
||||
""},
|
||||
{DI_POST_CTRL, 8, 1, 0, "",
|
||||
"di_vpp_out_en",
|
||||
""},
|
||||
/*--------------------------*/
|
||||
{VIU_MISC_CTRL0, 20, 1, 0, "VIU_MISC_CTRL0",
|
||||
"?",
|
||||
"?"},
|
||||
{VIU_MISC_CTRL0, 18, 1, 0, "",
|
||||
"Vdin0_wr_out_ctrl",
|
||||
"0: nr_inp to vdin; 1: vdin wr dout"},
|
||||
{VIU_MISC_CTRL0, 17, 1, 0, "",
|
||||
"Afbc_inp_sel",
|
||||
"0: mif to INP; 1: afbc to INP"},
|
||||
{VIU_MISC_CTRL0, 16, 1, 0, "",
|
||||
"di_mif0_en",
|
||||
" vd1(afbc) to di post(if0) enable"},
|
||||
/*--------------------------*/
|
||||
{DI_IF1_GEN_REG, 0, 1, 0, "DI_IF1_GEN_REG",
|
||||
"enable",
|
||||
""},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_IF1_GEN_REG3, 8, 2, 0, "DI_IF1_GEN_REG3",
|
||||
"cntl_bits_mode",
|
||||
"0:8bit;1:10bit 422;2:10bit 444"},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_IF2_GEN_REG3, 8, 2, 0, "DI_IF2_GEN_REG3",
|
||||
"cntl_bits_mode",
|
||||
"0:8bit;1:10bit 422;2:10bit 444"},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_IF0_GEN_REG3, 8, 2, 0, "DI_IF0_GEN_REG3",
|
||||
"cntl_bits_mode",
|
||||
"0:8bit;1:10bit 422;2:10bit 444"},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_POST_GL_CTRL, 31, 1, 0, "DI_POST_GL_CTRL",
|
||||
"post count enable",
|
||||
""},
|
||||
{DI_POST_GL_CTRL, 30, 1, 0, "",
|
||||
"post count reset",
|
||||
""},
|
||||
{DI_POST_GL_CTRL, 16, 14, 0, "",
|
||||
"total line number for post count",
|
||||
""},
|
||||
{DI_POST_GL_CTRL, 0, 14, 0, "",
|
||||
"the line number of post frame reset",
|
||||
""},
|
||||
|
||||
{TABLE_FLG_END, 0, 0, 0, "end", "end", ""},
|
||||
|
||||
};
|
||||
|
||||
/**********************/
|
||||
/* debug register */
|
||||
/**********************/
|
||||
static unsigned int get_reg_bits(unsigned int val, unsigned int bstart,
|
||||
unsigned int bw)
|
||||
{
|
||||
return((val &
|
||||
(((1L << bw) - 1) << bstart)) >> (bstart));
|
||||
}
|
||||
|
||||
static void dbg_reg_tab(struct seq_file *s, const struct reg_t *pRegTab)
|
||||
{
|
||||
struct reg_t creg;
|
||||
int i;
|
||||
unsigned int l_add;
|
||||
unsigned int val32 = 1, val;
|
||||
char *bname;
|
||||
char *info;
|
||||
|
||||
i = 0;
|
||||
l_add = 0;
|
||||
creg = pRegTab[i];
|
||||
|
||||
do {
|
||||
if (creg.add != l_add) {
|
||||
val32 = Rd(creg.add); /*RD*/
|
||||
seq_printf(s, "add:0x%x = 0x%08x, %s\n",
|
||||
creg.add, val32, creg.name);
|
||||
l_add = creg.add;
|
||||
}
|
||||
val = get_reg_bits(val32, creg.bit, creg.wid); /*RD_B*/
|
||||
|
||||
if (creg.bname)
|
||||
bname = creg.bname;
|
||||
else
|
||||
bname = "";
|
||||
if (creg.info)
|
||||
info = creg.info;
|
||||
else
|
||||
info = "";
|
||||
|
||||
seq_printf(s, "\tbit[%d,%d]:\t0x%x[%d]:\t%s:\t%s\n",
|
||||
creg.bit, creg.wid, val, val, bname, info);
|
||||
|
||||
i++;
|
||||
creg = pRegTab[i];
|
||||
if (i > TABLE_LEN_MAX) {
|
||||
pr_info("warn: too long, stop\n");
|
||||
break;
|
||||
}
|
||||
} while (creg.add != TABLE_FLG_END);
|
||||
}
|
||||
|
||||
int reg_con_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
dbg_reg_tab(seq, &rtab_contr[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reg_t rtab_cue_int[] = {
|
||||
/*--------------------------*/
|
||||
{NR2_CUE_CON_DIF0, 0, 32, 0x1400, "NR2_CUE_CON_DIF0",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_CON_DIF1, 0, 32, 0x80064, "NR2_CUE_CON_DIF1",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_CON_DIF2, 0, 32, 0x80064, "NR2_CUE_CON_DIF2",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_CON_DIF3, 0, 32, 0x80a0a, "NR2_CUE_CON_DIF3",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_PRG_DIF, 0, 32, 0x80a0a, "NR2_CUE_PRG_DIF",
|
||||
NULL,
|
||||
NULL},
|
||||
{TABLE_FLG_END, 0, 0, 0, "end", "end", ""},
|
||||
/*--------------------------*/
|
||||
};
|
||||
|
||||
/************************************************
|
||||
* register table
|
||||
************************************************/
|
||||
static bool di_g_rtab_cue(const struct reg_t **tab, unsigned int *tabsize)
|
||||
{
|
||||
*tab = &rtab_cue_int[0];
|
||||
*tabsize = ARRAY_SIZE(rtab_cue_int);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int dim_reg_read(unsigned int addr)
|
||||
{
|
||||
return aml_read_vcbus(addr);
|
||||
}
|
||||
|
||||
static const struct reg_acc di_pre_regset = {
|
||||
.wr = dim_DI_Wr,
|
||||
.rd = dim_reg_read,
|
||||
.bwr = dim_RDMA_WR_BITS,
|
||||
.brd = dim_RDMA_RD_BITS,
|
||||
};
|
||||
|
||||
static bool di_wr_tab(const struct reg_acc *ops,
|
||||
const struct reg_t *ptab, unsigned int tabsize)
|
||||
{
|
||||
int i;
|
||||
const struct reg_t *pl;
|
||||
|
||||
pl = ptab;
|
||||
|
||||
if (!ops ||
|
||||
!tabsize ||
|
||||
!ptab)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < tabsize; i++) {
|
||||
if (pl->add == TABLE_FLG_END ||
|
||||
i > TABLE_LEN_MAX) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pl->wid == 32)
|
||||
ops->wr(pl->add, pl->df_val);
|
||||
else
|
||||
ops->bwr(pl->add, pl->df_val, pl->bit, pl->wid);
|
||||
|
||||
pl++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dim_wr_cue_int(void)
|
||||
{
|
||||
const struct reg_t *ptab;
|
||||
unsigned int tabsize;
|
||||
|
||||
di_g_rtab_cue(&ptab, &tabsize);
|
||||
di_wr_tab(&di_pre_regset,
|
||||
ptab,
|
||||
tabsize);
|
||||
PR_INF("%s:finish\n", __func__);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int dim_reg_cue_int_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
dbg_reg_tab(seq, &rtab_cue_int[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
drivers/amlogic/media/di_multi/di_reg_tab.h
Normal file
26
drivers/amlogic/media/di_multi/di_reg_tab.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_reg_tab.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_REG_TABL_H__
|
||||
#define __DI_REG_TABL_H__
|
||||
|
||||
int reg_con_show(struct seq_file *seq, void *v);
|
||||
|
||||
bool dim_wr_cue_int(void);
|
||||
int dim_reg_cue_int_show(struct seq_file *seq, void *v);
|
||||
|
||||
#endif /*__DI_REG_TABL_H__*/
|
||||
754
drivers/amlogic/media/di_multi/di_sys.c
Normal file
754
drivers/amlogic/media/di_multi/di_sys.c
Normal file
@@ -0,0 +1,754 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_sys.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/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/cma.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
|
||||
/*dma_get_cma_size_int_byte*/
|
||||
#include <linux/amlogic/media/codec_mm/codec_mm.h>
|
||||
|
||||
#include "deinterlace_dbg.h"
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
#include "di_data.h"
|
||||
#include "di_dbg.h"
|
||||
#include "di_vframe.h"
|
||||
#include "di_task.h"
|
||||
#include "di_prc.h"
|
||||
#include "di_sys.h"
|
||||
#include "di_api.h"
|
||||
|
||||
#include "register.h"
|
||||
#include "nr_downscale.h"
|
||||
|
||||
static di_dev_t *di_pdev;
|
||||
|
||||
struct di_dev_s *get_dim_de_devp(void)
|
||||
{
|
||||
return di_pdev;
|
||||
}
|
||||
|
||||
unsigned int di_get_dts_nrds_en(void)
|
||||
{
|
||||
return get_dim_de_devp()->nrds_enable;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* mem
|
||||
*******************************************/
|
||||
|
||||
/********************************************/
|
||||
static ssize_t
|
||||
show_config(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t show_tvp_region(struct device *dev,
|
||||
struct device_attribute *attr, char *buff)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
struct di_dev_s *de_devp = get_dim_de_devp();
|
||||
|
||||
len = sprintf(buff, "segment DI:%lx - %lx (size:0x%x)\n",
|
||||
de_devp->mem_start,
|
||||
de_devp->mem_start + de_devp->mem_size - 1,
|
||||
de_devp->mem_size);
|
||||
return len;
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t
|
||||
show_log(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return dim_read_log(buf);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_frame_format(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int channel = get_current_channel(); /*debug only*/
|
||||
struct di_pre_stru_s *ppre = get_pre_stru(channel);
|
||||
|
||||
if (get_init_flag(channel))
|
||||
ret += sprintf(buf + ret, "%s\n",
|
||||
ppre->cur_prog_flag
|
||||
? "progressive" : "interlace");
|
||||
|
||||
else
|
||||
ret += sprintf(buf + ret, "%s\n", "null");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(frame_format, 0444, show_frame_format, NULL);
|
||||
static DEVICE_ATTR(config, 0640, show_config, store_config);
|
||||
static DEVICE_ATTR(debug, 0200, NULL, store_dbg);
|
||||
static DEVICE_ATTR(dump_pic, 0200, NULL, store_dump_mem);
|
||||
static DEVICE_ATTR(log, 0640, show_log, store_log);
|
||||
static DEVICE_ATTR(provider_vframe_status, 0444, show_vframe_status, NULL);
|
||||
static DEVICE_ATTR(tvp_region, 0444, show_tvp_region, NULL);
|
||||
|
||||
/********************************************/
|
||||
static int di_open(struct inode *node, struct file *file)
|
||||
{
|
||||
di_dev_t *di_in_devp;
|
||||
|
||||
/* Get the per-device structure that contains this cdev */
|
||||
di_in_devp = container_of(node->i_cdev, di_dev_t, cdev);
|
||||
file->private_data = di_in_devp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int di_release(struct inode *node, struct file *file)
|
||||
{
|
||||
/* di_dev_t *di_in_devp = file->private_data; */
|
||||
|
||||
/* Reset file pointer */
|
||||
|
||||
/* Release some other fields */
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long di_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
if (_IOC_TYPE(cmd) != _DI_) {
|
||||
PR_ERR("%s invalid command: %u\n", __func__, cmd);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
dbg_reg("no pq\n");
|
||||
return 0;
|
||||
#endif
|
||||
switch (cmd) {
|
||||
case AMDI_IOC_SET_PQ_PARM:
|
||||
ret = dim_pq_load_io(arg);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long di_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
arg = (unsigned long)compat_ptr(arg);
|
||||
ret = di_ioctl(file, cmd, arg);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct file_operations di_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = di_open,
|
||||
.release = di_release,
|
||||
.unlocked_ioctl = di_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = di_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int dim_rev_mem(struct di_dev_s *di_devp)
|
||||
{
|
||||
unsigned int ch;
|
||||
unsigned int o_size;
|
||||
unsigned long rmstart;
|
||||
unsigned int rmsize;
|
||||
unsigned int flg_map;
|
||||
|
||||
if (di_devp && !di_devp->flag_cma) {
|
||||
dil_get_rev_mem(&rmstart, &rmsize);
|
||||
dil_get_flg(&flg_map);
|
||||
if (!rmstart) {
|
||||
PR_ERR("%s:reserved mem start add is 0\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
di_devp->mem_start = rmstart;
|
||||
di_devp->mem_size = rmsize;
|
||||
|
||||
if (!flg_map)
|
||||
di_devp->flags |= DI_MAP_FLAG;
|
||||
|
||||
o_size = rmsize / DI_CHANNEL_NUB;
|
||||
|
||||
for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
|
||||
di_set_mem_info(ch,
|
||||
di_devp->mem_start + (o_size * ch),
|
||||
o_size);
|
||||
PR_INF("rmem:ch[%d]:start:0x%lx, size:%uB\n",
|
||||
ch,
|
||||
(di_devp->mem_start + (o_size * ch)),
|
||||
o_size);
|
||||
}
|
||||
PR_INF("rmem:0x%lx, size %uMB.\n",
|
||||
di_devp->mem_start, (di_devp->mem_size >> 20));
|
||||
|
||||
di_devp->mem_flg = true;
|
||||
return 0;
|
||||
}
|
||||
PR_INF("%s:no dev or no rev mem\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool dim_rev_mem_check(void)/*tmp*/
|
||||
{
|
||||
di_dev_t *di_devp = get_dim_de_devp();
|
||||
|
||||
if (di_devp && !di_devp->flag_cma && di_devp->mem_flg)
|
||||
return true;
|
||||
|
||||
if (!di_devp) {
|
||||
PR_ERR("%s:no dev\n", __func__);
|
||||
return false;
|
||||
}
|
||||
PR_INF("%s\n", __func__);
|
||||
dim_rev_mem(di_devp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ARY_MATCH (1)
|
||||
#ifdef ARY_MATCH
|
||||
|
||||
static const struct di_meson_data data_g12a = {
|
||||
.name = "dim_g12a",
|
||||
};
|
||||
|
||||
static const struct di_meson_data data_sm1 = {
|
||||
.name = "dim_sm1",
|
||||
};
|
||||
|
||||
/* #ifdef CONFIG_USE_OF */
|
||||
static const struct of_device_id amlogic_deinterlace_dt_match[] = {
|
||||
/*{ .compatible = "amlogic, deinterlace", },*/
|
||||
{ .compatible = "amlogic, dim-g12a",
|
||||
.data = &data_g12a,
|
||||
}, { .compatible = "amlogic, dim-g12b",
|
||||
.data = &data_sm1,
|
||||
}, { .compatible = "amlogic, dim-sm1",
|
||||
.data = &data_sm1,
|
||||
}, {}
|
||||
};
|
||||
#endif
|
||||
static int dim_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
int i;
|
||||
#ifdef ARY_MATCH
|
||||
const struct of_device_id *match;
|
||||
struct di_data_l_s *pdata;
|
||||
#endif
|
||||
PR_INF("%s:\n", __func__);
|
||||
|
||||
#if 1 /*move from init to here*/
|
||||
|
||||
di_pdev = kzalloc(sizeof(*di_pdev), GFP_KERNEL);
|
||||
if (!di_pdev) {
|
||||
PR_ERR("%s fail to allocate memory.\n", __func__);
|
||||
goto fail_kmalloc_dev;
|
||||
}
|
||||
|
||||
/******************/
|
||||
ret = alloc_chrdev_region(&di_pdev->devno, 0, DI_COUNT, DEVICE_NAME);
|
||||
if (ret < 0) {
|
||||
PR_ERR("%s: failed to allocate major number\n", __func__);
|
||||
goto fail_alloc_cdev_region;
|
||||
}
|
||||
PR_INF("%s: major %d\n", __func__, MAJOR(di_pdev->devno));
|
||||
di_pdev->pclss = class_create(THIS_MODULE, CLASS_NAME);
|
||||
if (IS_ERR(di_pdev->pclss)) {
|
||||
ret = PTR_ERR(di_pdev->pclss);
|
||||
PR_ERR("%s: failed to create class\n", __func__);
|
||||
goto fail_class_create;
|
||||
}
|
||||
#endif
|
||||
|
||||
di_devp = di_pdev;
|
||||
/* *********new********* */
|
||||
di_pdev->data_l = NULL;
|
||||
di_pdev->data_l = kzalloc(sizeof(struct di_data_l_s), GFP_KERNEL);
|
||||
if (!di_pdev->data_l) {
|
||||
PR_ERR("%s fail to allocate data l.\n", __func__);
|
||||
goto fail_kmalloc_datal;
|
||||
}
|
||||
/*memset(di_pdev->data_l, 0, sizeof(struct di_data_l_s));*/
|
||||
/*pr_info("\tdata size: %ld\n", sizeof(struct di_data_l_s));*/
|
||||
/************************/
|
||||
if (!dip_prob())
|
||||
goto fail_cdev_add;
|
||||
|
||||
di_devp->flags |= DI_SUSPEND_FLAG;
|
||||
cdev_init(&di_devp->cdev, &di_fops);
|
||||
di_devp->cdev.owner = THIS_MODULE;
|
||||
ret = cdev_add(&di_devp->cdev, di_devp->devno, DI_COUNT);
|
||||
if (ret)
|
||||
goto fail_cdev_add;
|
||||
|
||||
di_devp->devt = MKDEV(MAJOR(di_devp->devno), 0);
|
||||
di_devp->dev = device_create(di_devp->pclss, &pdev->dev,
|
||||
di_devp->devt, di_devp, "di%d", 0);
|
||||
|
||||
if (!di_devp->dev) {
|
||||
pr_error("device_create create error\n");
|
||||
goto fail_cdev_add;
|
||||
}
|
||||
dev_set_drvdata(di_devp->dev, di_devp);
|
||||
platform_set_drvdata(pdev, di_devp);
|
||||
|
||||
#ifdef ARY_MATCH
|
||||
/************************/
|
||||
match = of_match_device(amlogic_deinterlace_dt_match,
|
||||
&pdev->dev);
|
||||
if (!match) {
|
||||
PR_ERR("%s,no matched table\n", __func__);
|
||||
goto fail_cdev_add;
|
||||
}
|
||||
pdata = (struct di_data_l_s *)di_pdev->data_l;
|
||||
pdata->mdata = match->data;
|
||||
PR_INF("match name: %s\n", pdata->mdata->name);
|
||||
#endif
|
||||
|
||||
ret = of_reserved_mem_device_init(&pdev->dev);
|
||||
if (ret != 0)
|
||||
PR_INF("no reserved mem.\n");
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"flag_cma", &di_devp->flag_cma);
|
||||
if (ret)
|
||||
PR_ERR("DI-%s: get flag_cma error.\n", __func__);
|
||||
else
|
||||
PR_INF("flag_cma=%d\n", di_devp->flag_cma);
|
||||
|
||||
dim_rev_mem(di_devp);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"nrds-enable", &di_devp->nrds_enable);
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"pps-enable", &di_devp->pps_enable);
|
||||
|
||||
/*di pre h scaling down :sm1 tm2*/
|
||||
/*pre_hsc_down_en;*/
|
||||
di_devp->h_sc_down_en = di_mp_uit_get(eDI_MP_pre_hsc_down_en);
|
||||
|
||||
if (di_devp->flag_cma >= 1) {
|
||||
#ifdef CONFIG_CMA
|
||||
di_devp->pdev = pdev;
|
||||
di_devp->flags |= DI_MAP_FLAG;
|
||||
#if 0
|
||||
di_devp->mem_size = dma_get_cma_size_int_byte(&pdev->dev);
|
||||
#else
|
||||
if (di_devp->flag_cma == 1 ||
|
||||
di_devp->flag_cma == 2) {
|
||||
di_devp->mem_size
|
||||
= dma_get_cma_size_int_byte(&pdev->dev);
|
||||
PR_INF("mem size from dts:0x%x\n", di_devp->mem_size);
|
||||
}
|
||||
|
||||
if (di_devp->mem_size <= 0x800000) {/*need check??*/
|
||||
di_devp->mem_size = 0x2800000;
|
||||
/*(flag_cma ? 3) reserved in*/
|
||||
/*codec mm : cma in codec mm*/
|
||||
if (di_devp->flag_cma != 3) {
|
||||
/*no di cma, try use*/
|
||||
/*cma from codec mm*/
|
||||
di_devp->flag_cma = 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pr_info("DI: CMA size 0x%x.\n", di_devp->mem_size);
|
||||
if (di_devp->flag_cma == 2) {
|
||||
if (dim_cma_alloc_total(di_devp))
|
||||
dip_cma_st_set_ready_all();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
dip_cma_st_set_ready_all();
|
||||
}
|
||||
/* mutex_init(&di_devp->cma_mutex); */
|
||||
INIT_LIST_HEAD(&di_devp->pq_table_list);
|
||||
|
||||
atomic_set(&di_devp->pq_flag, 0);
|
||||
|
||||
di_devp->pre_irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
|
||||
pr_info("pre_irq:%d\n",
|
||||
di_devp->pre_irq);
|
||||
di_devp->post_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);
|
||||
pr_info("post_irq:%d\n",
|
||||
di_devp->post_irq);
|
||||
|
||||
di_pr_info("%s allocate rdma channel %d.\n", __func__,
|
||||
di_devp->rdma_handle);
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {
|
||||
dim_get_vpu_clkb(&pdev->dev, di_devp);
|
||||
#ifdef CLK_TREE_SUPPORT
|
||||
clk_prepare_enable(di_devp->vpu_clkb);
|
||||
pr_info("DI:enable vpu clkb.\n");
|
||||
#else
|
||||
aml_write_hiubus(HHI_VPU_CLKB_CNTL, 0x1000100);
|
||||
#endif
|
||||
}
|
||||
di_devp->flags &= (~DI_SUSPEND_FLAG);
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"buffer-size", &di_devp->buffer_size);
|
||||
if (ret)
|
||||
PR_ERR("DI-%s: get buffer size error.\n", __func__);
|
||||
|
||||
/* set flag to indicate that post_wr is supportted */
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"post-wr-support",
|
||||
&di_devp->post_wr_support);
|
||||
if (ret)
|
||||
dimp_set(eDI_MP_post_wr_support, 0);/*post_wr_support = 0;*/
|
||||
else /*post_wr_support = di_devp->post_wr_support;*/
|
||||
dimp_set(eDI_MP_post_wr_support, di_devp->post_wr_support);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"nr10bit-support",
|
||||
&di_devp->nr10bit_support);
|
||||
if (ret)
|
||||
dimp_set(eDI_MP_nr10bit_support, 0);/*nr10bit_support = 0;*/
|
||||
else /*nr10bit_support = di_devp->nr10bit_support;*/
|
||||
dimp_set(eDI_MP_nr10bit_support, di_devp->nr10bit_support);
|
||||
|
||||
#ifdef DI_USE_FIXED_CANVAS_IDX
|
||||
if (dim_get_canvas()) {
|
||||
pr_dbg("DI get canvas error.\n");
|
||||
ret = -EEXIST;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
device_create_file(di_devp->dev, &dev_attr_config);
|
||||
device_create_file(di_devp->dev, &dev_attr_debug);
|
||||
device_create_file(di_devp->dev, &dev_attr_dump_pic);
|
||||
device_create_file(di_devp->dev, &dev_attr_log);
|
||||
device_create_file(di_devp->dev, &dev_attr_provider_vframe_status);
|
||||
device_create_file(di_devp->dev, &dev_attr_frame_format);
|
||||
device_create_file(di_devp->dev, &dev_attr_tvp_region);
|
||||
|
||||
/*pd_device_files_add*/
|
||||
get_ops_pd()->prob(di_devp->dev);
|
||||
|
||||
get_ops_nr()->nr_drv_init(di_devp->dev);
|
||||
|
||||
for (i = 0; i < DI_CHANNEL_NUB; i++) {
|
||||
set_init_flag(i, false);
|
||||
set_reg_flag(i, false);
|
||||
}
|
||||
|
||||
set_or_act_flag(true);
|
||||
/*PR_INF("\t 11\n");*/
|
||||
ret = devm_request_irq(&pdev->dev, di_devp->pre_irq, &dim_irq,
|
||||
IRQF_SHARED,
|
||||
"pre_di", (void *)"pre_di");
|
||||
if (di_devp->post_wr_support) {
|
||||
ret = devm_request_irq(&pdev->dev, di_devp->post_irq,
|
||||
&dim_post_irq,
|
||||
IRQF_SHARED, "post_di",
|
||||
(void *)"post_di");
|
||||
}
|
||||
|
||||
di_devp->sema_flg = 1; /*di_sema_init_flag = 1;*/
|
||||
dimh_hw_init(dimp_get(eDI_MP_pulldown_enable),
|
||||
dimp_get(eDI_MP_mcpre_en));
|
||||
|
||||
dim_set_di_flag();
|
||||
|
||||
task_start();
|
||||
|
||||
post_mif_sw(false);
|
||||
|
||||
dim_debugfs_init(); /*2018-07-18 add debugfs*/
|
||||
|
||||
dimh_patch_post_update_mc_sw(DI_MC_SW_IC, true);
|
||||
|
||||
pr_info("%s:ok\n", __func__);
|
||||
return ret;
|
||||
|
||||
fail_cdev_add:
|
||||
pr_info("%s:fail_cdev_add\n", __func__);
|
||||
kfree(di_devp->data_l);
|
||||
|
||||
fail_kmalloc_datal:
|
||||
pr_info("%s:fail_kmalloc datal\n", __func__);
|
||||
|
||||
#if 1 /*move from init*/
|
||||
/*fail_pdrv_register:*/
|
||||
class_destroy(di_pdev->pclss);
|
||||
fail_class_create:
|
||||
unregister_chrdev_region(di_pdev->devno, DI_COUNT);
|
||||
fail_alloc_cdev_region:
|
||||
kfree(di_pdev);
|
||||
fail_kmalloc_dev:
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dim_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
|
||||
PR_INF("%s:\n", __func__);
|
||||
di_devp = platform_get_drvdata(pdev);
|
||||
|
||||
dimh_hw_uninit();
|
||||
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
|
||||
clk_disable_unprepare(di_devp->vpu_clkb);
|
||||
|
||||
di_devp->di_event = 0xff;
|
||||
|
||||
dim_uninit_buf(1, 0);/*channel 0*/
|
||||
di_set_flg_hw_int(false);
|
||||
|
||||
task_stop();
|
||||
|
||||
dim_rdma_exit();
|
||||
|
||||
/* Remove the cdev */
|
||||
device_remove_file(di_devp->dev, &dev_attr_config);
|
||||
device_remove_file(di_devp->dev, &dev_attr_debug);
|
||||
device_remove_file(di_devp->dev, &dev_attr_log);
|
||||
device_remove_file(di_devp->dev, &dev_attr_dump_pic);
|
||||
device_remove_file(di_devp->dev, &dev_attr_provider_vframe_status);
|
||||
device_remove_file(di_devp->dev, &dev_attr_frame_format);
|
||||
device_remove_file(di_devp->dev, &dev_attr_tvp_region);
|
||||
/*pd_device_files_del*/
|
||||
get_ops_pd()->remove(di_devp->dev);
|
||||
get_ops_nr()->nr_drv_uninit(di_devp->dev);
|
||||
cdev_del(&di_devp->cdev);
|
||||
|
||||
if (di_devp->flag_cma == 2) {
|
||||
if (dma_release_from_contiguous(&pdev->dev,
|
||||
di_devp->total_pages,
|
||||
di_devp->mem_size >> PAGE_SHIFT)) {
|
||||
di_devp->total_pages = NULL;
|
||||
di_devp->mem_start = 0;
|
||||
pr_dbg("DI CMA total release ok.\n");
|
||||
} else {
|
||||
pr_dbg("DI CMA total release fail.\n");
|
||||
}
|
||||
if (di_pdev->nrds_enable) {
|
||||
dim_nr_ds_buf_uninit(di_pdev->flag_cma,
|
||||
&pdev->dev);
|
||||
}
|
||||
}
|
||||
device_destroy(di_devp->pclss, di_devp->devno);
|
||||
|
||||
/* free drvdata */
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
#if 1 /*move to remove*/
|
||||
class_destroy(di_pdev->pclss);
|
||||
|
||||
dim_debugfs_exit();
|
||||
|
||||
dip_exit();
|
||||
unregister_chrdev_region(di_pdev->devno, DI_COUNT);
|
||||
#endif
|
||||
|
||||
kfree(di_devp->data_l);
|
||||
kfree(di_pdev);
|
||||
|
||||
PR_INF("%s:finish\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dim_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
int i;
|
||||
|
||||
di_devp = platform_get_drvdata(pdev);
|
||||
|
||||
for (i = 0; i < DI_CHANNEL_NUB; i++)
|
||||
set_init_flag(i, false);
|
||||
|
||||
if (is_meson_txlx_cpu())
|
||||
dim_top_gate_control(true, true);
|
||||
else
|
||||
dim_DI_Wr(DI_CLKG_CTRL, 0x2);
|
||||
|
||||
if (!is_meson_txlx_cpu())
|
||||
diext_clk_b_sw(false);
|
||||
|
||||
PR_INF("%s.\n", __func__);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static void di_clear_for_suspend(struct di_dev_s *di_devp)
|
||||
{
|
||||
unsigned int channel = get_current_channel(); /*tmp*/
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
di_vframe_unreg(channel);/*have flag*/
|
||||
|
||||
if (dip_chst_get(channel) != eDI_TOP_STATE_IDLE)
|
||||
dim_unreg_process_irq(channel);
|
||||
|
||||
dip_cma_close();
|
||||
pr_info("%s end\n", __func__);
|
||||
}
|
||||
|
||||
/* must called after lcd */
|
||||
static int di_suspend(struct device *dev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
|
||||
di_devp = dev_get_drvdata(dev);
|
||||
di_devp->flags |= DI_SUSPEND_FLAG;
|
||||
|
||||
di_clear_for_suspend(di_devp);
|
||||
|
||||
if (!is_meson_txlx_cpu())
|
||||
diext_clk_b_sw(false);
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD))
|
||||
clk_disable_unprepare(di_devp->vpu_clkb);
|
||||
PR_INF("%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* must called before lcd */
|
||||
static int di_resume(struct device *dev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
|
||||
PR_INF("%s\n", __func__);
|
||||
di_devp = dev_get_drvdata(dev);
|
||||
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL))
|
||||
clk_prepare_enable(di_devp->vpu_clkb);
|
||||
|
||||
di_devp->flags &= ~DI_SUSPEND_FLAG;
|
||||
|
||||
/************/
|
||||
PR_INF("%s finish\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops di_pm_ops = {
|
||||
.suspend_late = di_suspend,
|
||||
.resume_early = di_resume,
|
||||
};
|
||||
#endif
|
||||
#ifndef ARY_MATCH
|
||||
/* #ifdef CONFIG_USE_OF */
|
||||
static const struct of_device_id amlogic_deinterlace_dt_match[] = {
|
||||
/*{ .compatible = "amlogic, deinterlace", },*/
|
||||
{ .compatible = "amlogic, dim-g12a", },
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
/* #else */
|
||||
/* #define amlogic_deinterlace_dt_match NULL */
|
||||
/* #endif */
|
||||
|
||||
static struct platform_driver di_driver = {
|
||||
.probe = dim_probe,
|
||||
.remove = dim_remove,
|
||||
.shutdown = dim_shutdown,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = amlogic_deinterlace_dt_match,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &di_pm_ops,
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
static int __init dim_module_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
PR_INF("%s\n", __func__);
|
||||
|
||||
ret = platform_driver_register(&di_driver);
|
||||
if (ret != 0) {
|
||||
PR_ERR("%s: failed to register driver\n", __func__);
|
||||
/*goto fail_pdrv_register;*/
|
||||
return -ENODEV;
|
||||
}
|
||||
PR_INF("%s finish\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dim_module_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&di_driver);
|
||||
PR_INF("%s: ok.\n", __func__);
|
||||
}
|
||||
|
||||
module_init(dim_module_init);
|
||||
module_exit(dim_module_exit);
|
||||
|
||||
MODULE_DESCRIPTION("AMLOGIC MULTI-DI driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("4.0.0");
|
||||
|
||||
26
drivers/amlogic/media/di_multi/di_sys.h
Normal file
26
drivers/amlogic/media/di_multi/di_sys.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_sys.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_SYS_H__
|
||||
#define __DI_SYS_H__
|
||||
|
||||
#define DEVICE_NAME "di_multi"
|
||||
#define CLASS_NAME "deinterlace"
|
||||
|
||||
bool dim_rev_mem_check(void);
|
||||
|
||||
#endif /*__DI_SYS_H__*/
|
||||
315
drivers/amlogic/media/di_multi/di_task.c
Normal file
315
drivers/amlogic/media/di_multi/di_task.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_task.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/kthread.h> /*ary add*/
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
|
||||
#include "di_task.h"
|
||||
#include "di_vframe.h"
|
||||
|
||||
static void task_wakeup(struct di_task *tsk);
|
||||
|
||||
unsigned int di_dbg_task_flg; /*debug only*/
|
||||
|
||||
bool task_send_cmd(unsigned int cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
unsigned int val;
|
||||
|
||||
dbg_reg("%s:cmd[%d]:\n", __func__, cmd);
|
||||
if (kfifo_is_full(&tsk->fifo_cmd)) {
|
||||
if (kfifo_out(&tsk->fifo_cmd, &val, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int)) {
|
||||
PR_ERR("%s:can't out\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
PR_ERR("%s:lost cmd[%d]\n", __func__, val);
|
||||
tsk->err_cmd_cnt++;
|
||||
/*return false;*/
|
||||
}
|
||||
kfifo_in_spinlocked(&tsk->fifo_cmd, &cmd, sizeof(unsigned int),
|
||||
&tsk->lock_cmd);
|
||||
|
||||
task_wakeup(tsk);
|
||||
return true;
|
||||
}
|
||||
|
||||
void task_send_ready(void)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
task_wakeup(tsk);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool task_have_vf(unsigned int ch)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
task_wakeup(tsk);
|
||||
}
|
||||
#endif
|
||||
bool task_get_cmd(unsigned int *cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
unsigned int val;
|
||||
|
||||
if (kfifo_is_empty(&tsk->fifo_cmd))
|
||||
return false;
|
||||
|
||||
if (kfifo_out(&tsk->fifo_cmd, &val, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
|
||||
*cmd = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
void task_polling_cmd(void)
|
||||
{
|
||||
int i;
|
||||
union DI_L_CMD_BITS cmdbyte;
|
||||
|
||||
for (i = 0; i < MAX_KFIFO_L_CMD_NUB; i++) {
|
||||
if (!task_get_cmd(&cmdbyte.cmd32))
|
||||
break;
|
||||
dip_chst_process_reg(cmdbyte.b.ch);
|
||||
}
|
||||
}
|
||||
|
||||
static int task_is_exiting(struct di_task *tsk)
|
||||
{
|
||||
if (tsk->exit)
|
||||
return 1;
|
||||
|
||||
/* if (afepriv->dvbdev->writers == 1)
|
||||
* if (time_after_eq(jiffies, fepriv->release_jiffies +
|
||||
* dvb_shutdown_timeout * HZ))
|
||||
* return 1;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int task_should_wakeup(struct di_task *tsk)
|
||||
{
|
||||
if (tsk->wakeup) {
|
||||
tsk->wakeup = 0;
|
||||
/*dbg only dbg_tsk("wkg[%d]\n", di_dbg_task_flg);*/
|
||||
return 1;
|
||||
}
|
||||
return task_is_exiting(tsk);
|
||||
}
|
||||
|
||||
static void task_wakeup(struct di_task *tsk)
|
||||
{
|
||||
tsk->wakeup = 1;
|
||||
wake_up_interruptible(&tsk->wait_queue);
|
||||
/*dbg_tsk("wks[%d]\n", di_dbg_task_flg);*/
|
||||
}
|
||||
|
||||
static int di_test_thread(void *data)
|
||||
{
|
||||
struct di_task *tsk = data;
|
||||
bool semheld = false;
|
||||
|
||||
tsk->delay = HZ;
|
||||
tsk->status = 0;
|
||||
tsk->wakeup = 0;
|
||||
#if 0
|
||||
tsk->reinitialise = 0;
|
||||
tsk->needfinish = 0;
|
||||
tsk->finishflg = 0;
|
||||
#endif
|
||||
set_freezable();
|
||||
while (1) {
|
||||
up(&tsk->sem);/* is locked when we enter the thread... */
|
||||
restart:
|
||||
wait_event_interruptible_timeout(tsk->wait_queue,
|
||||
task_should_wakeup(tsk) ||
|
||||
kthread_should_stop() ||
|
||||
freezing(current),
|
||||
tsk->delay);
|
||||
di_dbg_task_flg = 1;
|
||||
|
||||
if (kthread_should_stop() || task_is_exiting(tsk)) {
|
||||
/* got signal or quitting */
|
||||
if (!down_interruptible(&tsk->sem))
|
||||
semheld = true;
|
||||
tsk->exit = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (try_to_freeze())
|
||||
goto restart;
|
||||
|
||||
if (down_interruptible(&tsk->sem))
|
||||
break;
|
||||
#if 0
|
||||
if (tsk->reinitialise) {
|
||||
/*dvb_frontend_init(fe);*/
|
||||
|
||||
tsk->reinitialise = 0;
|
||||
}
|
||||
#endif
|
||||
di_dbg_task_flg = 2;
|
||||
task_polling_cmd();
|
||||
di_dbg_task_flg = 3;
|
||||
dip_chst_process_ch();
|
||||
di_dbg_task_flg = 4;
|
||||
if (get_reg_flag_all())
|
||||
dip_hw_process();
|
||||
|
||||
di_dbg_task_flg = 0;
|
||||
}
|
||||
|
||||
tsk->thread = NULL;
|
||||
if (kthread_should_stop())
|
||||
tsk->exit = 1;
|
||||
else
|
||||
tsk->exit = 0;
|
||||
/*mb();*/
|
||||
|
||||
if (semheld)
|
||||
up(&tsk->sem);
|
||||
|
||||
task_wakeup(tsk);/*?*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void task_stop(void/*struct di_task *tsk*/)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
#if 1 /*not use cmd*/
|
||||
pr_info(".");
|
||||
/*--------------------*/
|
||||
/*cmd buf*/
|
||||
if (tsk->flg_cmd) {
|
||||
kfifo_free(&tsk->fifo_cmd);
|
||||
tsk->flg_cmd = 0;
|
||||
}
|
||||
/*tsk->lock_cmd = SPIN_LOCK_UNLOCKED;*/
|
||||
spin_lock_init(&tsk->lock_cmd);
|
||||
tsk->err_cmd_cnt = 0;
|
||||
/*--------------------*/
|
||||
#endif
|
||||
tsk->exit = 1;
|
||||
/*mb();*/
|
||||
|
||||
if (!tsk->thread)
|
||||
return;
|
||||
|
||||
kthread_stop(tsk->thread);
|
||||
|
||||
sema_init(&tsk->sem, 1);
|
||||
tsk->status = 0;
|
||||
|
||||
/* paranoia check in case a signal arrived */
|
||||
if (tsk->thread)
|
||||
PR_ERR("warning: thread %p won't exit\n", tsk->thread);
|
||||
}
|
||||
|
||||
int task_start(void)
|
||||
{
|
||||
int ret;
|
||||
int flg_err;
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
struct task_struct *fe_thread;
|
||||
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
|
||||
|
||||
pr_info(".");
|
||||
flg_err = 0;
|
||||
#if 1 /*not use cmd*/
|
||||
/*--------------------*/
|
||||
/*cmd buf*/
|
||||
/*tsk->lock_cmd = SPIN_LOCK_UNLOCKED;*/
|
||||
spin_lock_init(&tsk->lock_cmd);
|
||||
tsk->err_cmd_cnt = 0;
|
||||
ret = kfifo_alloc(&tsk->fifo_cmd,
|
||||
sizeof(unsigned int) * MAX_KFIFO_L_CMD_NUB,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
tsk->flg_cmd = false;
|
||||
PR_ERR("%s:can't get kfifo\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
tsk->flg_cmd = true;
|
||||
|
||||
#endif
|
||||
/*--------------------*/
|
||||
sema_init(&tsk->sem, 1);
|
||||
init_waitqueue_head(&tsk->wait_queue);
|
||||
|
||||
if (tsk->thread) {
|
||||
if (!tsk->exit)
|
||||
return 0;
|
||||
|
||||
task_stop();
|
||||
}
|
||||
|
||||
if (signal_pending(current)) {
|
||||
if (tsk->flg_cmd) {
|
||||
kfifo_free(&tsk->fifo_cmd);
|
||||
tsk->flg_cmd = 0;
|
||||
}
|
||||
return -EINTR;
|
||||
}
|
||||
if (down_interruptible(&tsk->sem)) {
|
||||
if (tsk->flg_cmd) {
|
||||
kfifo_free(&tsk->fifo_cmd);
|
||||
tsk->flg_cmd = 0;
|
||||
}
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
tsk->status = 0;
|
||||
tsk->exit = 0;
|
||||
tsk->thread = NULL;
|
||||
/*mb();*/
|
||||
|
||||
fe_thread = kthread_run(di_test_thread, tsk, "aml-ditest-0");
|
||||
if (IS_ERR(fe_thread)) {
|
||||
ret = PTR_ERR(fe_thread);
|
||||
PR_ERR(" failed to start kthread (%d)\n", ret);
|
||||
up(&tsk->sem);
|
||||
tsk->flg_init = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sched_setscheduler_nocheck(fe_thread, SCHED_FIFO, ¶m);
|
||||
tsk->flg_init = 1;
|
||||
tsk->thread = fe_thread;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dbg_task(void)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
tsk->status = 1;
|
||||
task_wakeup(tsk);
|
||||
}
|
||||
36
drivers/amlogic/media/di_multi/di_task.h
Normal file
36
drivers/amlogic/media/di_multi/di_task.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_task.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_TASK_H__
|
||||
#define __DI_TASK_H__
|
||||
|
||||
extern unsigned int di_dbg_task_flg; /*debug only*/
|
||||
|
||||
enum eTSK_STATE {
|
||||
eTSK_STATE_IDLE,
|
||||
eTSK_STATE_WORKING,
|
||||
};
|
||||
|
||||
void task_stop(void);
|
||||
int task_start(void);
|
||||
|
||||
void dbg_task(void);
|
||||
|
||||
bool task_send_cmd(unsigned int cmd);
|
||||
void task_send_ready(void);
|
||||
|
||||
#endif /*__DI_TASK_H__*/
|
||||
556
drivers/amlogic/media/di_multi/di_vframe.c
Normal file
556
drivers/amlogic/media/di_multi/di_vframe.c
Normal file
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_vframe.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/semaphore.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
#include "di_pre.h"
|
||||
#include "di_prc.h"
|
||||
#include "di_dbg.h"
|
||||
|
||||
#include "di_vframe.h"
|
||||
|
||||
struct dev_vfram_t *get_dev_vframe(unsigned int ch)
|
||||
{
|
||||
if (ch < DI_CHANNEL_NUB)
|
||||
return &get_datal()->ch_data[ch].vfm;
|
||||
|
||||
pr_info("err:%s ch overflow %d\n", __func__, ch);
|
||||
return &get_datal()->ch_data[0].vfm;
|
||||
}
|
||||
|
||||
const char * const di_rev_name[4] = {
|
||||
"deinterlace",
|
||||
"dimulti.1",
|
||||
"dimulti.2",
|
||||
"dimulti.3",
|
||||
};
|
||||
|
||||
void dev_vframe_reg(struct dev_vfram_t *pvfm)
|
||||
{
|
||||
if (pvfm->reg) {
|
||||
PR_WARN("duplicate reg\n");
|
||||
return;
|
||||
}
|
||||
vf_reg_provider(&pvfm->di_vf_prov);
|
||||
vf_notify_receiver(pvfm->name, VFRAME_EVENT_PROVIDER_START, NULL);
|
||||
pvfm->reg = 1;
|
||||
}
|
||||
|
||||
void dev_vframe_unreg(struct dev_vfram_t *pvfm)
|
||||
{
|
||||
if (pvfm->reg) {
|
||||
vf_unreg_provider(&pvfm->di_vf_prov);
|
||||
pvfm->reg = 0;
|
||||
} else {
|
||||
PR_WARN("duplicate ureg\n");
|
||||
}
|
||||
}
|
||||
|
||||
void di_vframe_reg(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
dev_vframe_reg(pvfm);
|
||||
}
|
||||
|
||||
void di_vframe_unreg(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
dev_vframe_unreg(pvfm);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
const char * const di_receiver_event_cmd[] = {
|
||||
"",
|
||||
"_UNREG",
|
||||
"_LIGHT_UNREG",
|
||||
"_START",
|
||||
NULL, /* "_VFRAME_READY", */
|
||||
NULL, /* "_QUREY_STATE", */
|
||||
"_RESET",
|
||||
NULL, /* "_FORCE_BLACKOUT", */
|
||||
"_REG",
|
||||
"_LIGHT_UNREG_RETURN_VFRAME",
|
||||
NULL, /* "_DPBUF_CONFIG", */
|
||||
NULL, /* "_QUREY_VDIN2NR", */
|
||||
NULL, /* "_SET_3D_VFRAME_INTERLEAVE", */
|
||||
NULL, /* "_FR_HINT", */
|
||||
NULL, /* "_FR_END_HINT", */
|
||||
NULL, /* "_QUREY_DISPLAY_INFO", */
|
||||
NULL, /* "_PROPERTY_CHANGED", */
|
||||
};
|
||||
|
||||
#define VFRAME_EVENT_PROVIDER_CMD_MAX 16
|
||||
|
||||
static int di_receiver_event_fun(int type, void *data, void *arg)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
unsigned int ch;
|
||||
int ret = 0;
|
||||
|
||||
ch = *(int *)arg;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
if (type <= VFRAME_EVENT_PROVIDER_CMD_MAX &&
|
||||
di_receiver_event_cmd[type]) {
|
||||
dbg_ev("ch[%d]:%s,%d:%s\n", ch, __func__,
|
||||
type,
|
||||
di_receiver_event_cmd[type]);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case VFRAME_EVENT_PROVIDER_UNREG:
|
||||
ret = di_ori_event_unreg(ch);
|
||||
/* task_send_cmd(LCMD1(eCMD_UNREG, 0));*/
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_REG:
|
||||
/*dev_vframe_reg(pvfm);*/
|
||||
ret = di_ori_event_reg(data, ch);
|
||||
/* task_send_cmd(LCMD1(eCMD_REG, 0));*/
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_START:
|
||||
break;
|
||||
|
||||
case VFRAME_EVENT_PROVIDER_LIGHT_UNREG:
|
||||
ret = di_ori_event_light_unreg(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_VFRAME_READY:
|
||||
ret = di_ori_event_ready(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_QUREY_STATE:
|
||||
ret = di_ori_event_qurey_state(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_RESET:
|
||||
ret = di_ori_event_reset(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME:
|
||||
ret = di_ori_event_light_unreg_revframe(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR:
|
||||
ret = di_ori_event_qurey_vdin2nr(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE:
|
||||
di_ori_event_set_3D(type, data, ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_FR_HINT:
|
||||
case VFRAME_EVENT_PROVIDER_FR_END_HINT:
|
||||
vf_notify_receiver(pvfm->name, type, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct vframe_receiver_op_s di_vf_receiver = {
|
||||
.event_cb = di_receiver_event_fun
|
||||
};
|
||||
|
||||
bool vf_type_is_prog(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_TYPEMASK) == 0 ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_interlace(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_INTERLACE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_top(unsigned int type)
|
||||
{
|
||||
bool ret = ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP)
|
||||
? true : false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_bottom(unsigned int type)
|
||||
{
|
||||
bool ret = ((type & VIDTYPE_INTERLACE_BOTTOM)
|
||||
== VIDTYPE_INTERLACE_BOTTOM)
|
||||
? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_inter_first(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_INTERLACE_TOP) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_mvc(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_MVC) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_no_video_en(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_NO_VIDEO_ENABLE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU422(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_422) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU_FIELD(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_FIELD) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU_SINGLE(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_SINGLE_PLANE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU444(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_444) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIUNV21(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_NV21) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_vscale_dis(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VSCALE_DISABLE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_canvas_toggle(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_CANVAS_TOGGLE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_pre_interlace(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_PRE_INTERLACE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_highrun(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_HIGHRUN) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_compress(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_COMPRESS) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_pic(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_PIC) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_scatter(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_SCATTER) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_vd2(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VD2) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool is_bypss_complete(struct dev_vfram_t *pvfm)
|
||||
{
|
||||
return pvfm->bypass_complete;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool is_reg(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
return pvfm->reg;
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_bypass_complete(struct dev_vfram_t *pvfm, bool on)
|
||||
{
|
||||
if (on)
|
||||
pvfm->bypass_complete = true;
|
||||
else
|
||||
pvfm->bypass_complete = false;
|
||||
}
|
||||
|
||||
void set_bypass2_complete(unsigned int ch, bool on)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
set_bypass_complete(pvfm, on);
|
||||
}
|
||||
|
||||
bool is_bypss2_complete(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
return is_bypss_complete(pvfm);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void set_reg(unsigned int ch, int on)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
if (on)
|
||||
pvfm->reg = true;
|
||||
else
|
||||
pvfm->reg = false;
|
||||
}
|
||||
#endif
|
||||
static struct vframe_s *di_vf_peek(void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
|
||||
/*dim_print("%s:ch[%d]\n",__func__,ch);*/
|
||||
if (di_is_pause(ch))
|
||||
return NULL;
|
||||
|
||||
if (is_bypss2_complete(ch))
|
||||
return pw_vf_peek(ch);
|
||||
else
|
||||
return di_vf_l_peek(ch);
|
||||
}
|
||||
|
||||
static struct vframe_s *di_vf_get(void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
/*struct vframe_s *vfm;*/
|
||||
|
||||
dim_tr_ops.post_get2(5);
|
||||
if (di_is_pause(ch))
|
||||
return NULL;
|
||||
|
||||
di_pause_step_done(ch);
|
||||
|
||||
/*pvfm = get_dev_vframe(ch);*/
|
||||
|
||||
if (is_bypss2_complete(ch))
|
||||
#if 0
|
||||
vfm = pw_vf_peek(ch);
|
||||
if (dim_bypass_detect(ch, vfm))
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
return pw_vf_get(ch);
|
||||
|
||||
return di_vf_l_get(ch);
|
||||
}
|
||||
|
||||
static void di_vf_put(struct vframe_s *vf, void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
|
||||
if (is_bypss2_complete(ch)) {
|
||||
pw_vf_put(vf, ch);
|
||||
pw_vf_notify_provider(ch,
|
||||
VFRAME_EVENT_RECEIVER_PUT, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
di_vf_l_put(vf, ch);
|
||||
}
|
||||
|
||||
static int di_event_cb(int type, void *data, void *private_data)
|
||||
{
|
||||
if (type == VFRAME_EVENT_RECEIVER_FORCE_UNREG) {
|
||||
pr_info("%s: RECEIVER_FORCE_UNREG return\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int di_vf_states(struct vframe_states *states, void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
|
||||
if (!states)
|
||||
return -1;
|
||||
|
||||
dim_print("%s:ch[%d]\n", __func__, ch);
|
||||
|
||||
di_vf_l_states(states, ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct vframe_operations_s deinterlace_vf_provider = {
|
||||
.peek = di_vf_peek,
|
||||
.get = di_vf_get,
|
||||
.put = di_vf_put,
|
||||
.event_cb = di_event_cb,
|
||||
.vf_states = di_vf_states,
|
||||
};
|
||||
|
||||
#if 1
|
||||
struct vframe_s *pw_vf_get(unsigned int ch)
|
||||
{
|
||||
sum_g_inc(ch);
|
||||
return vf_get(di_rev_name[ch]);
|
||||
}
|
||||
|
||||
struct vframe_s *pw_vf_peek(unsigned int ch)
|
||||
{
|
||||
return vf_peek(di_rev_name[ch]);
|
||||
}
|
||||
|
||||
void pw_vf_put(struct vframe_s *vf, unsigned int ch)
|
||||
{
|
||||
sum_p_inc(ch);
|
||||
vf_put(vf, di_rev_name[ch]);
|
||||
}
|
||||
|
||||
int pw_vf_notify_provider(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_provider(di_rev_name[channel], event_type, data);
|
||||
}
|
||||
|
||||
int pw_vf_notify_receiver(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_receiver(di_rev_name[channel], event_type, data);
|
||||
}
|
||||
|
||||
void pw_vf_light_unreg_provider(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
struct vframe_provider_s *prov;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
prov = &pvfm->di_vf_prov;
|
||||
vf_light_unreg_provider(prov);
|
||||
}
|
||||
|
||||
#else
|
||||
struct vframe_s *pw_vf_get(unsigned int channel)
|
||||
{
|
||||
return vf_get(VFM_NAME);
|
||||
}
|
||||
|
||||
struct vframe_s *pw_vf_peek(unsigned int channel)
|
||||
{
|
||||
return vf_peek(VFM_NAME);
|
||||
}
|
||||
|
||||
void pw_vf_put(struct vframe_s *vf, unsigned int channel)
|
||||
{
|
||||
vf_put(vf, VFM_NAME);
|
||||
}
|
||||
|
||||
int pw_vf_notify_provider(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_provider(VFM_NAME, event_type, data);
|
||||
}
|
||||
|
||||
int pw_vf_notify_receiver(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_receiver(VFM_NAME, event_type, data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void dev_vframe_exit(void)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
int ch;
|
||||
|
||||
for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
|
||||
pvfm = get_dev_vframe(ch);
|
||||
vf_unreg_provider(&pvfm->di_vf_prov);
|
||||
vf_unreg_receiver(&pvfm->di_vf_recv);
|
||||
}
|
||||
pr_info("%s finish\n", __func__);
|
||||
}
|
||||
|
||||
void dev_vframe_init(void)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
int ch;
|
||||
|
||||
for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
|
||||
pvfm = get_dev_vframe(ch);
|
||||
pvfm->name = di_rev_name[ch];
|
||||
pvfm->indx = ch;
|
||||
/*set_bypass_complete(pvfm, true);*/ /*test only*/
|
||||
|
||||
/*receiver:*/
|
||||
vf_receiver_init(&pvfm->di_vf_recv, pvfm->name,
|
||||
&di_vf_receiver, &pvfm->indx);
|
||||
vf_reg_receiver(&pvfm->di_vf_recv);
|
||||
|
||||
/*provider:*/
|
||||
vf_provider_init(&pvfm->di_vf_prov, pvfm->name,
|
||||
&deinterlace_vf_provider, &pvfm->indx);
|
||||
}
|
||||
pr_info("%s finish\n", __func__);
|
||||
}
|
||||
68
drivers/amlogic/media/di_multi/di_vframe.h
Normal file
68
drivers/amlogic/media/di_multi/di_vframe.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_vframe.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_VFRAME_H__
|
||||
#define __DI_VFRAME_H__
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_provider.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_receiver.h>
|
||||
|
||||
void dev_vframe_init(void);
|
||||
void dev_vframe_exit(void);
|
||||
void di_vframe_reg(unsigned int ch);
|
||||
void di_vframe_unreg(unsigned int ch);
|
||||
|
||||
bool vf_type_is_prog(unsigned int type);
|
||||
bool vf_type_is_interlace(unsigned int type);
|
||||
bool vf_type_is_top(unsigned int type);
|
||||
bool vf_type_is_bottom(unsigned int type);
|
||||
bool vf_type_is_inter_first(unsigned int type);
|
||||
bool vf_type_is_mvc(unsigned int type);
|
||||
bool vf_type_is_no_video_en(unsigned int type);
|
||||
bool vf_type_is_VIU422(unsigned int type);
|
||||
bool vf_type_is_VIU_FIELD(unsigned int type);
|
||||
bool vf_type_is_VIU_SINGLE(unsigned int type);
|
||||
bool vf_type_is_VIU444(unsigned int type);
|
||||
bool vf_type_is_VIUNV21(unsigned int type);
|
||||
bool vf_type_is_vscale_dis(unsigned int type);
|
||||
bool vf_type_is_canvas_toggle(unsigned int type);
|
||||
bool vf_type_is_pre_interlace(unsigned int type);
|
||||
bool vf_type_is_highrun(unsigned int type);
|
||||
bool vf_type_is_compress(unsigned int type);
|
||||
bool vf_type_is_pic(unsigned int type);
|
||||
bool vf_type_is_scatter(unsigned int type);
|
||||
bool vf_type_is_vd2(unsigned int type);
|
||||
|
||||
extern const char * const di_rev_name[4];
|
||||
|
||||
struct vframe_s *pw_vf_get(unsigned int ch);
|
||||
struct vframe_s *pw_vf_peek(unsigned int ch);
|
||||
void pw_vf_put(struct vframe_s *vf, unsigned int ch);
|
||||
int pw_vf_notify_provider(unsigned int channel,
|
||||
int event_type,
|
||||
void *data);
|
||||
int pw_vf_notify_receiver(unsigned int channel,
|
||||
int event_type,
|
||||
void *data);
|
||||
void pw_vf_light_unreg_provider(unsigned int ch);
|
||||
|
||||
void set_bypass2_complete(unsigned int ch, bool on);
|
||||
bool is_bypss_complete(struct dev_vfram_t *pvfm);
|
||||
bool is_bypss2_complete(unsigned int ch);
|
||||
|
||||
#endif /*__DI_VFRAME_H__*/
|
||||
71
drivers/amlogic/media/di_multi/dim_trace.h
Normal file
71
drivers/amlogic/media/di_multi/dim_trace.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/dim_trace.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM dim
|
||||
|
||||
#if !defined(_DIM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _DIM_TRACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
/* single lifecycle events */
|
||||
DECLARE_EVENT_CLASS(di_event_class,
|
||||
TP_PROTO(const char *name, int field_cnt, unsigned long time),
|
||||
TP_ARGS(name, field_cnt, time),
|
||||
TP_STRUCT__entry(
|
||||
__string(name, name)
|
||||
__field(int, field_cnt)
|
||||
__field(unsigned long, time)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(name, name);
|
||||
__entry->field_cnt = field_cnt;
|
||||
__entry->time = time;
|
||||
),
|
||||
TP_printk("[%s-%-4dth-%lums]", __get_str(name),
|
||||
__entry->field_cnt, __entry->time)
|
||||
);
|
||||
|
||||
#define DEFINE_DI_EVENT(name) \
|
||||
DEFINE_EVENT(di_event_class, name, \
|
||||
TP_PROTO(const char *name, int field_cnt, unsigned long time), \
|
||||
TP_ARGS(name, field_cnt, time))
|
||||
|
||||
DEFINE_DI_EVENT(dim_pre);
|
||||
DEFINE_DI_EVENT(dim_post);
|
||||
/*2019-06-18*/
|
||||
DEFINE_DI_EVENT(dim_pre_getxx);
|
||||
DEFINE_DI_EVENT(dim_pre_setxx);
|
||||
DEFINE_DI_EVENT(dim_pre_ready);
|
||||
DEFINE_DI_EVENT(dim_pst_ready);
|
||||
DEFINE_DI_EVENT(dim_pst_getxx);
|
||||
DEFINE_DI_EVENT(dim_pst_setxx);
|
||||
DEFINE_DI_EVENT(dim_pst_irxxx);
|
||||
DEFINE_DI_EVENT(dim_pst_doing);
|
||||
DEFINE_DI_EVENT(dim_pst_peekx);
|
||||
DEFINE_DI_EVENT(dim_pst_get2x);
|
||||
|
||||
#endif /* _DIM_TRACE_H */
|
||||
|
||||
#if 0
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#define TRACE_INCLUDE_FILE deinterlace_trace
|
||||
#include <trace/define_trace.h>
|
||||
#endif
|
||||
218
drivers/amlogic/media/di_multi/nr_downscale.c
Normal file
218
drivers/amlogic/media/di_multi/nr_downscale.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/nr_downscale.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/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/amlogic/iomap.h>
|
||||
#include <linux/amlogic/media/canvas/canvas.h>
|
||||
#include <linux/amlogic/media/canvas/canvas_mgr.h>
|
||||
#include "register.h"
|
||||
#include "nr_downscale.h"
|
||||
#include "deinterlace.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_api.h"
|
||||
|
||||
static struct nr_ds_s nrds_dev;
|
||||
|
||||
static void nr_ds_hw_init(unsigned int width, unsigned int height)
|
||||
{
|
||||
unsigned char h_step = 0, v_step = 0;
|
||||
unsigned int width_out, height_out;
|
||||
|
||||
width_out = NR_DS_WIDTH;
|
||||
height_out = NR_DS_HEIGHT;
|
||||
|
||||
h_step = width / width_out;
|
||||
v_step = height / height_out;
|
||||
|
||||
/*Switch MIF to NR_DS*/
|
||||
dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 3, 5, 2);
|
||||
/* config dsbuf_ocol*/
|
||||
dim_RDMA_WR_BITS(NR_DS_BUF_SIZE_REG, width_out, 0, 8);
|
||||
/* config dsbuf_orow*/
|
||||
dim_RDMA_WR_BITS(NR_DS_BUF_SIZE_REG, height_out, 8, 8);
|
||||
|
||||
dim_RDMA_WR_BITS(NRDSWR_X, (width_out - 1), 0, 13);
|
||||
dim_RDMA_WR_BITS(NRDSWR_Y, (height_out - 1), 0, 13);
|
||||
|
||||
dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, (height_out - 1), 0, 13);
|
||||
dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, (width_out - 1), 16, 13);
|
||||
/* little endian */
|
||||
dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, 1, 13, 1);
|
||||
|
||||
dim_RDMA_WR_BITS(NR_DS_CTRL, v_step, 16, 6);
|
||||
dim_RDMA_WR_BITS(NR_DS_CTRL, h_step, 24, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* init nr ds buffer
|
||||
*/
|
||||
void dim_nr_ds_buf_init(unsigned int cma_flag, unsigned long mem_start,
|
||||
struct device *dev)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
bool ret;
|
||||
struct dim_mm_s omm;
|
||||
|
||||
if (cma_flag == 0) {
|
||||
nrds_dev.nrds_addr = mem_start;
|
||||
} else {
|
||||
#if 0
|
||||
nrds_dev.nrds_pages = dma_alloc_from_contiguous(dev,
|
||||
NR_DS_PAGE_NUM, 0);
|
||||
if (nrds_dev.nrds_pages)
|
||||
nrds_dev.nrds_addr = page_to_phys(nrds_dev.nrds_pages);
|
||||
else
|
||||
PR_ERR("DI: alloc nr ds mem error.\n");
|
||||
#else
|
||||
ret = dim_mm_alloc(cma_flag, NR_DS_PAGE_NUM, &omm);
|
||||
if (ret) {
|
||||
nrds_dev.nrds_pages = omm.ppage;
|
||||
nrds_dev.nrds_addr = omm.addr;
|
||||
} else {
|
||||
PR_ERR("alloc nr ds mem error.\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < NR_DS_BUF_NUM; i++)
|
||||
nrds_dev.buf[i] = nrds_dev.nrds_addr + (NR_DS_BUF_SIZE * i);
|
||||
nrds_dev.cur_buf_idx = 0;
|
||||
}
|
||||
|
||||
void dim_nr_ds_buf_uninit(unsigned int cma_flag, struct device *dev)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if (cma_flag == 0) {
|
||||
nrds_dev.nrds_addr = 0;
|
||||
} else {
|
||||
if (nrds_dev.nrds_pages) {
|
||||
#if 0
|
||||
dma_release_from_contiguous(dev,
|
||||
nrds_dev.nrds_pages,
|
||||
NR_DS_PAGE_NUM);
|
||||
#else
|
||||
dim_mm_release(cma_flag,
|
||||
nrds_dev.nrds_pages,
|
||||
NR_DS_PAGE_NUM,
|
||||
nrds_dev.nrds_addr);
|
||||
#endif
|
||||
nrds_dev.nrds_addr = 0;
|
||||
nrds_dev.nrds_pages = NULL;
|
||||
} else
|
||||
pr_info("DI: no release nr ds mem.\n");
|
||||
}
|
||||
for (i = 0; i < NR_DS_BUF_NUM; i++)
|
||||
nrds_dev.buf[i] = 0;
|
||||
nrds_dev.cur_buf_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* hw config, alloc canvas
|
||||
*/
|
||||
void dim_nr_ds_init(unsigned int width, unsigned int height)
|
||||
{
|
||||
nr_ds_hw_init(width, height);
|
||||
nrds_dev.field_num = 0;
|
||||
|
||||
if (nrds_dev.canvas_idx != 0)
|
||||
return;
|
||||
|
||||
if (ext_ops.canvas_pool_alloc_canvas_table("nr_ds",
|
||||
&nrds_dev.canvas_idx, 1, CANVAS_MAP_TYPE_1)) {
|
||||
PR_ERR("%s alloc nrds canvas error.\n", __func__);
|
||||
return;
|
||||
}
|
||||
pr_info("%s alloc nrds canvas %u.\n",
|
||||
__func__, nrds_dev.canvas_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* config nr ds mif, switch buffer
|
||||
*/
|
||||
void dim_nr_ds_mif_config(void)
|
||||
{
|
||||
unsigned long mem_addr = 0;
|
||||
|
||||
mem_addr = nrds_dev.buf[nrds_dev.cur_buf_idx];
|
||||
canvas_config(nrds_dev.canvas_idx, mem_addr,
|
||||
NR_DS_WIDTH, NR_DS_HEIGHT, 0, 0);
|
||||
dim_RDMA_WR_BITS(NRDSWR_CTRL,
|
||||
nrds_dev.canvas_idx, 0, 8);
|
||||
dim_nr_ds_hw_ctrl(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* enable/disable nr ds mif&hw
|
||||
*/
|
||||
void dim_nr_ds_hw_ctrl(bool enable)
|
||||
{
|
||||
/*Switch MIF to NR_DS*/
|
||||
dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, enable ? 3 : 2, 5, 2);
|
||||
dim_RDMA_WR_BITS(NRDSWR_CTRL, enable ? 1 : 0, 12, 1);
|
||||
dim_RDMA_WR_BITS(NR_DS_CTRL, enable ? 1 : 0, 30, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* process in irq
|
||||
*/
|
||||
void dim_nr_ds_irq(void)
|
||||
{
|
||||
dim_nr_ds_hw_ctrl(false);
|
||||
nrds_dev.field_num++;
|
||||
nrds_dev.cur_buf_idx++;
|
||||
if (nrds_dev.cur_buf_idx >= NR_DS_BUF_NUM)
|
||||
nrds_dev.cur_buf_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get buf addr&size for dump
|
||||
*/
|
||||
void dim_get_nr_ds_buf(unsigned long *addr, unsigned long *size)
|
||||
{
|
||||
*addr = nrds_dev.nrds_addr;
|
||||
*size = NR_DS_BUF_SIZE;
|
||||
pr_info("%s addr 0x%lx, size 0x%lx.\n",
|
||||
__func__, *addr, *size);
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x37f9 ~ 0x37fc 0x3740 ~ 0x3743 8 regs
|
||||
*/
|
||||
void dim_dump_nrds_reg(unsigned int base_addr)
|
||||
{
|
||||
unsigned int i = 0x37f9;
|
||||
|
||||
pr_info("-----nrds reg start-----\n");
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (0x2006 << 2), i, dim_RDMA_RD(0x2006));
|
||||
for (i = 0x37f9; i < 0x37fd; i++)
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2), i, dim_RDMA_RD(i));
|
||||
for (i = 0x3740; i < 0x3744; i++)
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2), i, dim_RDMA_RD(i));
|
||||
pr_info("-----nrds reg end-----\n");
|
||||
}
|
||||
46
drivers/amlogic/media/di_multi/nr_downscale.h
Normal file
46
drivers/amlogic/media/di_multi/nr_downscale.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/nr_downscale.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 _NR_DS_H
|
||||
#define _NR_DS_H
|
||||
|
||||
#define NR_DS_WIDTH 128
|
||||
#define NR_DS_HEIGHT 96
|
||||
#define NR_DS_BUF_SIZE (96 << 7)
|
||||
#define NR_DS_BUF_NUM 6
|
||||
#define NR_DS_MEM_SIZE (NR_DS_BUF_SIZE * NR_DS_BUF_NUM)
|
||||
#define NR_DS_PAGE_NUM (NR_DS_MEM_SIZE >> PAGE_SHIFT)
|
||||
|
||||
struct nr_ds_s {
|
||||
unsigned int field_num;
|
||||
unsigned long nrds_addr;
|
||||
struct page *nrds_pages;
|
||||
unsigned int canvas_idx;
|
||||
unsigned char cur_buf_idx;
|
||||
unsigned long buf[NR_DS_BUF_NUM];
|
||||
};
|
||||
|
||||
void dim_nr_ds_buf_init(unsigned int cma_flag, unsigned long mem_start,
|
||||
struct device *dev);
|
||||
void dim_nr_ds_buf_uninit(unsigned int cma_flag, struct device *dev);
|
||||
void dim_nr_ds_init(unsigned int width, unsigned int height);
|
||||
void dim_nr_ds_mif_config(void);
|
||||
void dim_nr_ds_hw_ctrl(bool enable);
|
||||
void dim_nr_ds_irq(void);
|
||||
void dim_get_nr_ds_buf(unsigned long *addr, unsigned long *size);
|
||||
void dim_dump_nrds_reg(unsigned int base_addr);
|
||||
#endif
|
||||
4416
drivers/amlogic/media/di_multi/register.h
Normal file
4416
drivers/amlogic/media/di_multi/register.h
Normal file
File diff suppressed because it is too large
Load Diff
149
drivers/amlogic/media/di_multi/register_nr4.h
Normal file
149
drivers/amlogic/media/di_multi/register_nr4.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/register_nr4.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define NR4_DRT_CTRL ((0x2da4))
|
||||
#define NR4_DRT_YSAD_GAIN ((0x2da5))
|
||||
#define NR4_DRT_CSAD_GAIN ((0x2da6))
|
||||
#define NR4_DRT_SAD_ALP_CORE ((0x2da7))
|
||||
#define NR4_DRT_ALP_MINMAX ((0x2da8))
|
||||
#define NR4_SNR_CTRL_REG ((0x2da9))
|
||||
#define NR4_SNR_ALPHA0_MAX_MIN ((0x2daa))
|
||||
#define NR4_ALP0C_ERR2CURV_LIMIT0 ((0x2dab))
|
||||
#define NR4_ALP0C_ERR2CURV_LIMIT1 ((0x2dac))
|
||||
#define NR4_ALP0Y_ERR2CURV_LIMIT0 ((0x2dad))
|
||||
#define NR4_ALP0Y_ERR2CURV_LIMIT1 ((0x2dae))
|
||||
#define NR4_SNR_ALPA1_RATE_AND_OFST ((0x2daf))
|
||||
#define NR4_SNR_ALPHA1_MAX_MIN ((0x2db0))
|
||||
#define NR4_ALP1C_ERR2CURV_LIMIT0 ((0x2db1))
|
||||
#define NR4_ALP1C_ERR2CURV_LIMIT1 ((0x2db2))
|
||||
#define NR4_ALP1Y_ERR2CURV_LIMIT0 ((0x2db3))
|
||||
#define NR4_ALP1Y_ERR2CURV_LIMIT1 ((0x2db4))
|
||||
#define NR4_MTN_CTRL ((0x2db5))
|
||||
#define NR4_MTN_REF_PAR0 ((0x2db6))
|
||||
#define NR4_MTN_REF_PAR1 ((0x2db7))
|
||||
#define NR4_MCNR_LUMA_ENH_CTRL ((0x2db8))
|
||||
#define NR4_MCNR_LUMA_STAT_LIMTX ((0x2db9))
|
||||
#define NR4_MCNR_LUMA_STAT_LIMTY ((0x2dba))
|
||||
#define NR4_MCNR_LUMA_DIF_CALC ((0x2dbb))
|
||||
#define NR4_MCNR_LUMAPRE_CAL_PRAM ((0x2dbc))
|
||||
#define NR4_MCNR_LUMACUR_CAL_PRAM ((0x2dbd))
|
||||
#define NR4_MCNR_MV_CTRL_REG ((0x2dbe))
|
||||
#define NR4_MCNR_MV_GAIN0 ((0x2dbf))
|
||||
#define NR4_MCNR_LMV_PARM ((0x2dc0))
|
||||
#define NR4_MCNR_ALP0_REG (0x2dc1)
|
||||
#define NR4_MCNR_ALP1_AND_BET0_REG (0x2dc2)
|
||||
#define NR4_MCNR_BET1_AND_BET2_REG (0x2dc3)
|
||||
#define NR4_MCNR_AC_DC_CRTL (0x2dc4)
|
||||
#define NR4_MCNR_CM_CTRL0 (0x2dc5)
|
||||
#define NR4_MCNR_CM_PRAM (0x2dc6)
|
||||
#define NR4_MCNR_CM_RSHFT_ALP0 (0x2dc7)
|
||||
#define NR4_MCNR_BLUE_CENT (0x2dc8)
|
||||
#define NR4_MCNR_BLUE_GAIN_PAR0 (0x2dc9)
|
||||
#define NR4_MCNR_BLUE_GAIN_PAR1 (0x2dca)
|
||||
#define NR4_MCNR_CM_BLUE_CLIP0 (0x2dcb)
|
||||
#define NR4_MCNR_CM_BLUE_CLIP1 (0x2dcc)
|
||||
#define NR4_MCNR_GREEN_CENT (0x2dcd)
|
||||
#define NR4_MCNR_GREEN_GAIN_PAR0 (0x2dce)
|
||||
#define NR4_MCNR_GREEN_GAIN_PAR1 (0x2dcf)
|
||||
#define NR4_MCNR_GREEN_CLIP0 (0x2dd0)
|
||||
#define NR4_MCNR_GREEN_CLIP2 (0x2dd1)
|
||||
#define NR4_MCNR_SKIN_CENT (0x2dd2)
|
||||
#define NR4_MCNR_SKIN_GAIN_PAR0 (0x2dd3)
|
||||
#define NR4_MCNR_SKIN_GAIN_PAR1 (0x2dd4)
|
||||
#define NR4_MCNR_SKIN_CLIP0 (0x2dd5)
|
||||
#define NR4_MCNR_SKIN_CLIP1 (0x2dd6)
|
||||
#define NR4_MCNR_ALP1_GLB_CTRL (0x2dd7)
|
||||
#define NR4_MCNR_DC2NORM_LUT0 (0x2dd8)
|
||||
#define NR4_MCNR_DC2NORM_LUT1 (0x2dd9)
|
||||
#define NR4_MCNR_DC2NORM_LUT2 (0x2dda)
|
||||
#define NR4_MCNR_AC2NORM_LUT0 (0x2ddb)
|
||||
#define NR4_MCNR_AC2NORM_LUT1 (0x2ddc)
|
||||
#define NR4_MCNR_AC2NORM_LUT2 (0x2ddd)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT0 (0x2dde)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT1 (0x2ddf)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT2 (0x2de0)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT3 (0x2de1)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT0 (0x2de2)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT1 (0x2de3)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT2 (0x2de4)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT3 (0x2de5)
|
||||
#define NR4_MCNR_SAD2BET0_LUT0 (0x2de6)
|
||||
#define NR4_MCNR_SAD2BET0_LUT1 (0x2de7)
|
||||
#define NR4_MCNR_SAD2BET0_LUT2 (0x2de8)
|
||||
#define NR4_MCNR_SAD2BET0_LUT3 (0x2de9)
|
||||
#define NR4_MCNR_SAD2BET1_LUT0 (0x2dea)
|
||||
#define NR4_MCNR_SAD2BET1_LUT1 (0x2deb)
|
||||
#define NR4_MCNR_SAD2BET1_LUT2 (0x2dec)
|
||||
#define NR4_MCNR_SAD2BET1_LUT3 (0x2ded)
|
||||
#define NR4_MCNR_SAD2BET2_LUT0 (0x2dee)
|
||||
#define NR4_MCNR_SAD2BET2_LUT1 (0x2def)
|
||||
#define NR4_MCNR_SAD2BET2_LUT2 (0x2df0)
|
||||
#define NR4_MCNR_SAD2BET2_LUT3 (0x2df1)
|
||||
#define NR4_MCNR_RO_U_SUM (0x2df2)
|
||||
#define NR4_MCNR_RO_V_SUM (0x2df3)
|
||||
#define NR4_MCNR_RO_GRDU_SUM (0x2df4)
|
||||
#define NR4_MCNR_RO_GRDV_SUM (0x2df5)
|
||||
#define NR4_TOP_CTRL (0x2dff)
|
||||
#define NR4_MCNR_SAD_GAIN (0x3700)
|
||||
#define NR4_MCNR_LPF_CTRL (0x3701)
|
||||
#define NR4_MCNR_BLD_VS3LUT0 (0x3702)
|
||||
#define NR4_MCNR_BLD_VS3LUT1 (0x3703)
|
||||
#define NR4_MCNR_BLD_VS3LUT2 (0x3704)
|
||||
#define NR4_MCNR_BLD_VS2LUT0 (0x3705)
|
||||
#define NR4_MCNR_BLD_VS2LUT1 (0x3706)
|
||||
#define NR4_COEFBLT_LUT10 (0x3707)
|
||||
#define NR4_COEFBLT_LUT11 (0x3708)
|
||||
#define NR4_COEFBLT_LUT12 (0x3709)
|
||||
#define NR4_COEFBLT_LUT20 (0x370a)
|
||||
#define NR4_COEFBLT_LUT21 (0x370b)
|
||||
#define NR4_COEFBLT_LUT22 (0x370c)
|
||||
#define NR4_COEFBLT_LUT30 (0x370d)
|
||||
#define NR4_COEFBLT_LUT31 (0x370e)
|
||||
#define NR4_COEFBLT_LUT32 (0x370f)
|
||||
#define NR4_COEFBLT_CONV (0x3710)
|
||||
#define NR4_DBGWIN_YX0 (0x3711)
|
||||
#define NR4_DBGWIN_YX1 (0x3712)
|
||||
#define NR4_NM_X_CFG (0x3713)
|
||||
#define NR4_NM_Y_CFG (0x3714)
|
||||
#define NR4_NM_SAD_THD (0x3715)
|
||||
#define NR4_MCNR_BANDSPLIT_PRAM (0x3716)
|
||||
#define NR4_MCNR_ALP1_SGN_COR (0x3717)
|
||||
#define NR4_MCNR_ALP1_SGN_PRAM (0x3718)
|
||||
#define NR4_MCNR_ALP1_MVX_LUT1 (0x3719)
|
||||
#define NR4_MCNR_ALP1_MVX_LUT2 (0x371a)
|
||||
#define NR4_MCNR_ALP1_MVX_LUT3 (0x371b)
|
||||
#define NR4_MCNR_ALP1_LP_PRAM (0x371c)
|
||||
#define NR4_MCNR_ALP1_SGN_LUT1 (0x371d)
|
||||
#define NR4_MCNR_ALP1_SGN_LUT2 (0x371e)
|
||||
#define NR4_RO_NM_SAD_SUM (0x371f)
|
||||
#define NR4_RO_NM_SAD_CNT (0x3720)
|
||||
#define NR4_RO_NM_VAR_SUM (0x3721)
|
||||
#define NR4_RO_NM_VAR_SCNT (0x3722)
|
||||
#define NR4_RO_NM_VAR_MIN_MAX (0x3723)
|
||||
#define NR4_RO_NR4_DBGPIX_NUM (0x3724)
|
||||
#define NR4_RO_NR4_BLDVS2_SUM (0x3725)
|
||||
#define NR4_BLDVS3_SUM (0x3726)
|
||||
#define NR4_COEF12_SUM (0x3727)
|
||||
#define NR4_COEF123_SUM (0x3728)
|
||||
#define NR_DB_FLT_CTRL (0x3738)
|
||||
#define NR_DB_FLT_YC_THRD (0x3739)
|
||||
#define NR_DB_FLT_RANDLUT (0x373a)
|
||||
#define NR_DB_FLT_PXI_THRD (0x373b)
|
||||
#define NR_DB_FLT_SEED_Y (0x373c)
|
||||
#define NR_DB_FLT_SEED_V (0x373e)
|
||||
#define NR_DB_FLT_SEED3 (0x373f)
|
||||
#define LBUF_TOP_CTRL (0x2fff)
|
||||
@@ -52,6 +52,8 @@
|
||||
#define VIDTYPE_PRE_DI_AFBC 0x10000000
|
||||
#define VIDTYPE_RGB_444 0x20000000
|
||||
|
||||
/* 2019-04-22 Suggestions from brian.zhu*/
|
||||
#define VIDTYPE_DI_PW 0x40000000
|
||||
#define DISP_RATIO_FORCECONFIG 0x80000000
|
||||
#define DISP_RATIO_FORCE_NORMALWIDE 0x40000000
|
||||
#define DISP_RATIO_FORCE_FULL_STRETCH 0x20000000
|
||||
|
||||
Reference in New Issue
Block a user