BT1120 BT656驱动相关代码示例

news2025/4/20 6:12:21

前些年做视频输出项目的时候用过bt1120 tx与rx模块,现将部分代码进行记录整理。代码功能正常,可正常应用。

1. rx部分:

/*****************************************************************************
 * Copyright (C) 2021,All rights reserved.
 * Version     : V1.0
 * Description :
 *
 *****************************************************************************/

#ifndef _TS_bt1120RX_H_
#define _TS_bt1120RX_H_

//#include <linux/types.h>
#include <uapi/linux/types.h>
#include <linux/ioctl.h>

#ifdef __KERNEL__
#include <linux/time.h>
#else
#include <sys/time.h>
#endif


#ifdef __cplusplus
extern "C" {  /* C declaration in C++ */
#endif /* _cplusplus */

#define TRUE						(1)
#define FALSE						(0)
#define ERROR						(-1)

#define TS_bt1120RX_NAME "bt1120rx"
#define TS_bt1120RX_MISCDEV_MINOR	MISC_DYNAMIC_MINOR//243

/* command for ioctl() */
#define BT1120RX_IOC_MAGIC 'r'
#define BT1120RX_IOC_BIND_GROUP		_IOW(BT1120RX_IOC_MAGIC, 0, int)

#define BT1120RX_IOC_INIT			_IOW(BT1120RX_IOC_MAGIC, 1, int)
#define BT1120RX_IOC_REQBUFS		_IOW(BT1120RX_IOC_MAGIC, 2, int)
#define BT1120RX_IOC_STREAM			_IOW(BT1120RX_IOC_MAGIC, 3, int)
#define BT1120RX_IOC_QBUF			_IOW(BT1120RX_IOC_MAGIC, 4, int)
#define BT1120RX_IOC_DQBUF			_IOW(BT1120RX_IOC_MAGIC, 5, int)
#define BT1120RX_IOC_STATUS			_IOW(BT1120RX_IOC_MAGIC, 6, int)
#define BT1120RX_IOC_GET_CFG		_IOW(BT1120RX_IOC_MAGIC, 7, int)
#define BT1120RX_IOC_REST_HW		_IOW(BT1120RX_IOC_MAGIC, 8, int)

#define BT1120RX_FRME_MAX_PLANES	3

/* used in q/dq ioctl */
struct bt1120rx_frame_info {
	int index;	/* id of this frame for user space */

	/* buf fd */
	int fd;

	/*
	 * input or output info
	 * w <= 0xFFFF
	 * h <= 0xFFFF
	 */
	unsigned int w;
	unsigned int h;
	unsigned int paddr[BT1120RX_FRME_MAX_PLANES];
	/*
	 * if stride = 0, cal by driver
	 * stride[x] <= 0xFFFF
	 */
	unsigned int stride[BT1120RX_FRME_MAX_PLANES];

	/* config file info, just valid for input dev node */
	unsigned int cfg_paddr;
	unsigned int cfg_size;

	/* time stamp of this hw module when dq */
	struct timeval tv_this;
	/* time stamp when vin, may not exist */
	struct timeval tv_vin;
};

int bt1120rx_ClrIntr(u32 intrType);
#if 0
void dvpConfigScaling(bt1120rx_Config * dvpConfig,  bt1120_Rx_Regs * rx);
void dvpConfigGsg(bt1120rx_Config *dvpConfig);
void dvpConfigDecode(u16 srcWidth, u16 srcHeight);
void bt1120rx_config_bank_addr(bt1120rx_Config *dvpConfig);
void bt1120rx_EnIntr(u32 status);
u32 bt1120rx_GetIntrStatus(void);
u32 bt1120rx_GetIntrRawStatus(void);
u32 bt1120rx_GetRxStatus(void);
void bt1120rx_SoftRestDVP(bt1120_ctrl *dvpCtrl,
	bt1120_Rx_Regs *rx);
void bt1120rx_enable(void);
void bt1120rx_disable(void);
void bt1120rx_video_output_info(bt1120rx_Config *dvpConfig,
	bt1120_Rx_Regs *rx);
void bt1120rx_ready_info(bt1120rx_Config *dvpConfig,
	bt1120_Rx_Regs *rx);
void bt1120rx_test_status(bt1120rx_Config *dvpConfig,
	bt1120_Rx_Regs *rx);
void bt1120rx_dump_y_info(bt1120rx_Config *dvpConfig,
	bt1120_Rx_Regs *rx);
void bt1120rx_status_info(bt1120rx_Config *dvpConfig);
int bt1120rx_hw_init(bt1120rx_Config *dvpConfig);
void IOCTRL_ConfigDVPRx(void);
int32_t target_bt1120_init(int32_t idx,
	u32 *base, u32 *irq, void **handler);
void bt1120_rx_irqhandler(int32_t idx);
#endif
#ifdef __cplusplus
}
#endif

#endif /* _QW_bt1120RX_H_ */
/*****************************************************************************
 * Copyright (C) 2021,All rights reserved.
 * Description  : bt1120 rx driver;
 * bt1120 => YUV420 =>GSG=> 0RGB/YUV444/YUV422/U8
 *
 *****************************************************************************/
#define pr_fmt(fmt)	"bt1120rx_drv: " fmt

//#include <stdlib.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/reset.h>
#include <linux/delay.h>

#include <linux/interrupt.h>
#include <linux/mutex.h>

#include <linux/miscdevice.h>
#include <linux/of_reserved_mem.h>
#include <linux/dma-mapping.h>
#include <linux/printk.h>
#include <asm-generic/io.h>

#include <linux/uaccess.h>
#include <linux/slab.h> //kzalloc

#include "ts_bt1120rx.h"


#ifdef DEBUG
//#undef DEBUG
#endif
#ifdef DEBUG
static int bt_debug_level = 7;

#define bt_debug(level, fmt, args...)				\
	do {							\
		if (bt_debug_level >= level)			\
			pr_debug("%s:%d: " fmt,	\
				__func__, __LINE__, ##args);	\
	} while (0)
#else
#define bt_debug(level, fmt, args...) pr_debug(fmt, ##args)

#endif

#define bt_debug_enter() bt_debug(5, "enter\n")
#define bt_debug_leave() bt_debug(5, "leave\n")

#define bt_err(fmt, args...)				\
		pr_err("%s:%d: " fmt,		\
		       __func__, __LINE__, ##args)

#define bt_err_limited(fmt, args...)			\
		printk_ratelimited(KERN_ERR "%s:%d: " fmt,	\
		       __func__, __LINE__, ##args)

#define bt_info(fmt, args...)				\
		pr_info("%s:%d: " fmt,		\
		       __func__, __LINE__, ##args)

#define SETBIT(reg, bit)			\
	(reg = ((reg) | ((0x00000001) << (bit))))
#define RESETBIT(reg, bit)			\
	(reg = ((reg) & (~(0x00000001 << (bit)))))

#define DEC_BANK_ADDR_BASE			(0x20000000)

#define AXI_PIC_STRIDE_EN	(1)
#define AXI_PIC_STRIDE_DIS	(0)

#define NULL_PTR			((void *)0)

#define ERROR				(-1)

#define IOCTRL_BASE_ADDR	//0xFFF03000  //CHANGE

#define ID_MAX				32
#define SINC_INDEX_MAX		9
#define SC_INDEX_MAX		4

//BANK_NUMBER
#define BANK_NUMBER_0		0
#define BANK_NUMBER_1		1
#define BANK_NUMBER_2		2
#define BANK_NUMBER_3		3
#define BANK_NUMBER_4		4
#define BANK_NUMBER_5		5
#define BANK_NUMBER_6		6

//BANK INTERRUPT
#define INT_BANK0			(1 << 0)
#define INT_BANK1			(1 << 1)
#define INT_BANK2			(1 << 2)
#define INT_BANK3			(1 << 3)
#define INT_BANK4			(1 << 4)
#define INT_BANK5			(1 << 5)

//INTERRUPT EN
#define DVP_INT_EN			1
#define DVP_INT_DIS			0

//SINC EN
#define HZ_UV_EN			1
#define HZ_UV_DIS			0

#define HZ_Y_EN				1
#define HZ_Y_DIS			0

#define VT_UV_EN			1
#define VT_UV_DIS			0

#define VT_Y_EN				1
#define VT_Y_DIS			0

//SC EN
#define SC_HZ_EN			1
#define SC_HZ_DIS			0

#define SC_VT_EN			1
#define SC_VT_DIS			0

//DVP EN
#define DVP_DEC_EN			1
#define DVP_DEC_DIS			0

//DEC MODE
#define AUTO_DEC_MODE		1
#define MANUAL_DEC_MODE		0

//CHECK EN
#define DVP_CHECK_EN		1
#define DVP_CHECK_DIS		0

//RANGE EN
#define DVP_RANGE_EN		1
#define DVP_RANGE_DIS		0

//DATA MODE
#define DVP_DATA_MODE1		1
#define DVP_DATA_MODE0		0

//DVP SFT RST EN
#define DVP_SFT_RST_EN		1
#define DVP_SFT_RST_DIS		0

/*//PIC MODE
 * #define MODE_ORGB			0
 * #define MODE_RGB_DIV		1
 * #define MODE_UYVY			4
 * #define MODE_YUYV			5
 * #define MODE_IYUV			6
 * #define MODE_YUV4			7
 * #define MODE_U8				8
 */

//GSGS PARA
#define KR_V_DEF_VAL		409
#define KR_Y_DEF_VAL		298
#define KG_U_DEF_VAL		1948
#define KG_Y_DEF_VAL		298
#define KB_Y_DEF_VAL		298
#define KG_V_DEF_VAL		1840
#define KB_U_DEF_VAL		516

//VSYNC DELAY
#define VSYNC_DELAY_DEF		20

typedef enum _bt1120_Ctrl {
	bt1120_DEC_EN = 0,		// dec enable
	bt1120_DEC_MODE = 1,	// 0: manual 1: auto     ???
	bt1120_CHECK_EN = 2,	// timer baseline error check
	bt1120_RANGE_EN = 3,	// amplitude limit
	bt1120_DATA_MODE = 5,	// 0: Y high 8 bit 1: UV high 8 bit
	DVP_SFT_RST = 31,		// soft reset
} e_bt1120_Ctrl;

// input video config
typedef struct _bt1120_Video_Config {
	u16 bt1120_width_vld;	//[0:11] default 0x500 = 1280
	u16 bt1120_height_vld;	//[16:26] default 0x2d0 = 720
} bt1120_video_config;

// ap limit valid
typedef struct _bt1120_Range_Config {
	u8 bt1120_max_y_set;	//[0:7]   default 0xeb
	u8 bt1120_min_y_set;	//[8:15]  default 0x10
	u8 bt1120_max_c_set;	//[16:23] default 0xf0
	u8 bt1120_min_c_set;	//[24:31] default 0x10
} bt1120_range_config;

typedef struct _bt1120_Vsync_Config {
	u8 bt1120_vsync_delay;	//[0:5] default 0x14 = 20 [11 ~ 29]
} bt1120_vsync_config;

// readonly
typedef struct _bt1120_Video_Info1 {
	u8 bt1120_frame_size;	// [0:3] 0:720p	1:1080p(1920x1080)
	u8 bt1120_frame_freq;
	// [8:11] 0:25p 1:30p 2:50p 3:60p 4:50i 5:59.94i 6:12.5p 7:15p 8:20p
} bt1120_video_info1;

enum frame_size {
	FRAME_SIZE_720P = 0,
	FRAME_SIZE_1080P = 1,
};

typedef enum _frame_freq {
	FREQ_25P = 0,
	FREQ_30P,
	FREQ_50P,
	FREQ_60P,
	FREQ_50I,
	FREP_59_94I,
	FREQ_12_5P,
	FREQ_15P,
	FREQ_20P,
} e_frame_freq;

// readonly
typedef struct _bt1120_Video_Info2 {
	u16 bt1120_img_w_valid;	//[0:11]
	u16 bt1120_img_h_valid;	//[16:26]
} bt1120_video_info2;

// readonly
typedef struct _bt1120_Video_Info3 {
	u16 bt1120_img_w_all;	//[0:11] width all
	u16 bt1120_img_h_all;	//[16:26] height all
} bt1120_video_info3;

// readonly
typedef struct _bt1120_Status {
	u8 bt1120_video_lost;	//[0] not lock
	u8 bt1120_error_flg;
	//[8:10] 0:no error 1: no valid time base
	// 2:16bit Y and UV input no valid time base
	// 3: valid width error 4: valid heigh error
} bt1120_status;

typedef struct _Scale_Ratiok_Hz {
	u32 scale_ratiok_hz;	//[0:19] i_image_width * 65536 / i_sc_width
} scale_ratiok_hz;

typedef struct _Scale_Ratiok_Vt {
	u32 scale_ratiok_vt;	//[0:19] i_image_height *65536 / isc_height
} scale_ratiok_vt;

typedef struct _Sinc_Hz_Y_Coe0 {
	u32 sinc_hz_y_coe0;		//[0:26]	3 * 9bit
} sinc_hz_y_coe0;

typedef struct _Sinc_Hz_Y_Coe1 {
	u32 sinc_hz_y_coe1;		//[0:17]	2 * 9bit
} sinc_hz_y_coe1;

typedef struct _Sinc_Hz_UV_Coe0 {
	u32 sinc_hz_uv_coe0;	//[0:26]	3 * 9bit
} sinc_hz_uv_coe0;

typedef struct _Sinc_Hz_UV_Coe1 {
	u32 sinc_hz_uv_coe1;	//[0:17]	2 * 9bit
} sinc_hz_uv_coe1;

typedef struct _Sinc_Vt_Y_Coe0 {
	u32 sinc_vt_y_coe0;		//[0:26]	3 * 9bit
} sinc_vt_y_coe0;

typedef struct _Sinc_Vt_Y_Coe1 {
	u32 sinc_vt_y_coe1;		//[0:17]	2 * 9bit
} sinc_vt_y_coe1;

typedef struct _Sinc_Vt_UV_Coe0 {
	u32 sinc_vt_uv_coe0;	//[0:26]
} sinc_vt_uv_coe0;

typedef struct _Sinc_Vt_UV_Coe1 {
	u32 sinc_vt_uv_coe1;	//[0:17]
} sinc_vt_uv_coe1;

typedef enum _Sinc_En {
	SINC_VT_Y_EN = 0,
	SINC_VT_UV_EN = 4,
	SINC_HZ_Y_EN = 8,
	SINC_HZ_UV_EN = 12,
} e_sinc_en;

typedef struct _SINC_En {
	bool hz_uv_en;
	bool hz_y_en;
	bool vt_uv_en;
	bool vt_y_en;
}  sinc_en;

typedef enum _Sc_En {
	SC_VT_EN_BIT = 0,
	SC_HZ_EN_BIT = 4,
} e_sc_en;

typedef struct _SC_En {
	bool sc_hz_en;
	bool sc_vt_en;
}  sc_en;


typedef struct _Sc_Image_Info {
	u16 sc_width;	//[0:11] default 0x240, max support 1728
	u16 sc_height;	//[16:26] scaling width, default 0x2d0, max support 2592
} sc_image_info;

typedef enum _Pic_Mode {	//[0:3]
	ORGB = 0,		//ORGB = RGB888 = 0 R G B. 32BIT(X4)
	RGB_DIV = 1,	// RH BH GH 24BIT(X3)
	UYVY = 4,		// UYVY		16BIT(X2)
	YUYV = 5,		// YUYV		16BIT(X2)
	IYUV = 6,		// YH UH/2*W/2 VH/2*2/2 12BIT(X1.5)
	YUV4 = 7,		// YH UH VH 24BIT(X3)
	U8 = 8,			// YH		8BIT(X1)
} e_pic_mode;

typedef struct _Axi_Format_Stride0 {
	u16 pic_stride_en;	//[0:2] 0: plane continuous storage
	u32 pic_stride0;	//[16:29] 16-byte alignment
} axi_format_stride0;

typedef struct _Axi_Format_Stride1 {
	u32 pic_stride1;	//[0:11]	16-byte alignment
	u32 pic_stride2;	//[16:27]	...
} axi_format_stride1;

//readonly
typedef struct _Ready_Para0 {
	u16 ready_image_width;	//[0:11]
	u16 ready_image_height;	//[12:22]
	u8 ready_image_stride_en;
	//[24:26]	0: plane continuous storage
	u8 ready_image_mode;		//[28:31]	upload mode
} ready_para0;

//readonly
typedef struct _Ready_Para1 {
	u16 ready_image_stride0;	//[0:13] plane0 stride
	u16 ready_image_stride1;	//[16:27] plane1 stride
} ready_para1;

typedef struct _Ready_Para2 {
	u16 ready_image_stride2;	//[0:11]	plane2 stride
} ready_para2;

typedef enum _Frame_Info_Extr_En {
	FRAME_INFO_EXTRA_ENABLE = 0,
} e_frame_info_extr_en;


typedef enum _Frame_Simple_Period {
	EVERY_FRAME = 1,
	TWO_FRAME,
	THREE_FRAME,
	FOUR_FRAME,
	FIVE_FRAME,
	SIX_FRAME,
	SEVEN_FRAME,
} e_frame_simple_period;

typedef enum _Interupt_Enable {
	INTERUPT_ENABLE = 0,
} e_interupt_enable;

//readonly
typedef enum _Interupt_Status {
	INTERUPT_STATUS0 = 0,
	INTERUPT_STATUS1,
	INTERUPT_STATUS2,
	INTERUPT_STATUS3,
	INTERUPT_STATUS4,
	INTERUPT_STATUS5,
} e_interupt_status;

typedef enum _Inetrupt_Raw_Status {
	INTERUPT_RAW_STATUS0 = 0,
	INTERUPT_RAW_STATUS1,
	INTERUPT_RAW_STATUS2,
	INTERUPT_RAW_STATUS3,
	INTERUPT_RAW_STATUS4,
	INTERUPT_RAW_STATUS5,
} e_interupt_raw_status;


typedef enum _Interupt_Clear {
	INTERUPT_CLEAR0 = 0,
	INTERUPT_CLEAR1,
	INTERUPT_CLEAR2,
	INTERUPT_CLEAR3,
	INTERUPT_CLEAR4,
	INTERUPT_CLEAR5,
} e_interupt_clear;

//readonly
typedef enum _Test_Status {
	FIFO_Y_OVERFLOW = 0,
	FIFO_UV_OVERFLOW = 4,
} e_test_status;


typedef struct _DVP_En {
	bool bt1120_dec_en;
	bool bt1120_dec_mode;
	bool bt1120_check_en;
	bool bt1120_range_en;
	bool bt1120_data_mode;
	bool dvp_sft_rst;
} bt1120_ctrl;

typedef struct _DVP_Config {
	//user configure
	u32 src_width;
	u32 src_height;
	u32 dst_width;
	u32 dst_height;
	e_frame_freq frame_freq;
	void __iomem *mem_base;
	void *dma_vaddr;
	void *bank_vaddr[6][3];
	u32    dma_size;
	dma_addr_t dma_handler;
	u32 frame_index;
	u8 cur_bank;

	//tmp
	u32 src_img_size;
	u32 dst_img_size;
	u32 dst_pix_bits;	//rgb:4 yuv:2 yuv4:3 u8:1 iyuv:1.5

	//video config
	//u32 width_vld;
	//u32 height_vld;

	u32 hz_array_idx;	// (dst_width * 32) / src_width
	u32 vt_array_idx;	// (dst_height * 32) / src_height
	u32 sc_multiple;	// src_width / dst_width

	bt1120_ctrl bt1120_ctrl;
	u32 bt1120_ctrl_val;
	bt1120_video_config video_config; // src_width | src_height << 16

	//range config
	//u32 max_y_set;
	//u32 min_y_set;
	//u32 max_c_set;
	//u32 min_c_set;
	bt1120_range_config range_config;

	//vsync config
	//u32 vsync_delay;
	bt1120_vsync_config vsync_config;	//default 0x14

	//read-only
	bt1120_video_info1 output_info1;
	bt1120_video_info2 output_info2;
	bt1120_video_info3 output_info3;
	bt1120_status bt1120_status;

	scale_ratiok_hz scale_hz;
	scale_ratiok_vt scale_vt;

	sinc_hz_y_coe0	sinc_hz_y_coe0;
	sinc_hz_y_coe1	sinc_hz_y_coe1;
	sinc_hz_uv_coe0 sinc_hz_uv_coe0;
	sinc_hz_uv_coe1 sinc_hz_uv_coe1;

	sinc_en sinc_en;
	sc_en sc_en;
	u32 sinc_en_val;	//source from sinc_en
	u32 sc_en_val;		//source from sc_en
	sc_image_info sc_image_info;

	sinc_vt_y_coe0 sinc_vt_y_coe0;
	sinc_vt_y_coe1 sinc_vt_y_coe1;
	sinc_vt_uv_coe0 sinc_vt_uv_coe0;
	sinc_vt_uv_coe1 sinc_vt_uv_coe1;

	//scaling para
	u32 sc_coe[32][2];

	e_pic_mode pic_mode;

	u32 gsg_kr_v;
	u32 gsg_kr_y;
	u32 gsg_kg_u;
	u32 gsg_kg_y;
	u32 gsg_kb_y;
	u32 gsg_kg_v;
	u32 gsg_kb_u;

	axi_format_stride0 axi_fmt_stride0;
	axi_format_stride1 axi_fmt_stride1;

	//read-only
	u32 ready_bank_addr0;
	u32 ready_bank_addr1;
	u32 ready_bank_addr2;
	ready_para0 ready_para0;
	ready_para1 ready_para1;
	ready_para2 ready_para2;

	u32 frame_info_extr_en; // e_frame..
	//u32 frm_smp_period;
	u32 frame_sample_perid; // e_frame_sample_perid

	//u32* mem_src[6][3];
	u32 *bank_addr[6][3];

	u32 interupt_enable;	//e_interupt_enable
	u32 interupt_status;	//e_interupt_status
	u32 interupt_raw_status; //e_interupt_raw_status
	u32 interupt_clear;		//e_interupt_clear

	u32 bank_num;
	u32 test_status;		//e_test_status

	//read-only
	u32 bank_info[6][32];

} bt1120rx_Config;


typedef struct _bt1120_Rx_Regs {
	u32 bt1120_ctrl;			// 0x000
	u32 bt1120_video_config;
	u32 bt1120_range_config;
	u32 bt1120_vsync_config;
	u32 bt1120_video_info1;
	u32 bt1120_video_info2;
	u32 bt1120_video_info3;

	u32 bt1120_status;			// 0x1c
	u32 reserved_0[56];			// 56 x 4 = 224
	u32 scale_ratiok_hz;		// 0x100
	u32 scale_ratiok_vt;
	u32 sinc_hz_y_coe0;
	u32 sinc_hz_y_coe1;
	u32 sinc_hz_uv_coe0;
	u32 sinc_hz_uv_coe1;
	u32 sinc_en;
	u32 sc_en;
	u32 sc_image_info;
	u32 sinc_vt_y_coe0;
	u32 sinc_vt_y_coe1;
	u32 sinc_vt_uv_coe0;
	u32 sinc_vt_uv_coe1;		// 0x130
	u32 reserved_1[51];			// 51 x 4 = 204
	u32 sc_coe[32][2];			// 0x200
	u32 pic_mode;				// 0x300
	u32 gsgs_k0;
	u32 gsgs_k1;
	u32 gsgs_k2;
	u32 gsgs_k3;				// 0x310
	u32 reseverd_3[59];
	u32 axi_format_stride0;
	// 0x400, plane0 stride. How to configure ?
	u32 axi_format_stride1;		// plane1/2 stride
	u32 ready_bank_addr0;		// ro
	u32 ready_bank_addr1;		// ro
	u32 ready_bank_addr2;		// ro
	u32 ready_para0;			// ro
	u32 ready_para1;			// ro
	u32 ready_para2;			// ro
	u32 frame_info_extr_en;		// 128 size Y
	u32 frame_sample_period;
	u32 bank_addr[6][3];		// 16byte align
	u32 interupt_enable;
	u32 interupt_status;		// ro
	u32 interupt_raw_status;	// ro
	u32 interupt_clear;
	u32 bank_number;
	u32 test_status;			// 0x484
	u32 reserved_4[2];
	u32 bank_info[6][32];			// 0x490
} bt1120_Rx_Regs;

static bt1120_Rx_Regs *rx;//(struct _bt1120_Rx_Regs *)bt1120_RX_BASE;
struct ts_bt1120rx *g_bt_rx;


static uint32_t ReadReg32(uint32_t *addr)
{
	return readl(addr);
}

static void WriteReg32(uint32_t *addr, uint32_t value)
{
	writel(value, addr);
}

int sc_coe0[ID_MAX][SC_INDEX_MAX] = {
	{-3, 257, 3, -1},
	{-9, 258, 10, -3},
	{-14, 257, 18, -5},
	{-19, 255, 27, -7},
	{-23, 252, 36, -9},
	{-26, 247, 46, -11},
	{-29, 243, 56, -14},
	{-31, 237, 66, -16},
	{-33, 231, 77, -19},
	{-35, 224, 88, -21},
	{-36, 216, 99, -23},
	{-36, 207, 111, -26},
	{-36, 198, 122, -28},
	{-36, 188, 134, -30},
	{-35, 178, 144, -31},
	{-34, 167, 156, -33},
	{-33, 156, 167, -34},
	{-31, 145, 177, -35},
	{-30, 134, 188, -36},
	{-28, 122, 198, -36},
	{-26, 111, 207, -36},
	{-23, 99, 216, -36},
	{-21, 88, 224, -35},
	{-19, 77, 231, -33},
	{-16, 66, 237, -31},
	{-14, 56, 243, -29},
	{-11, 46, 247, -26},
	{-9, 36, 252, -23},
	{-7, 27, 255, -19},
	{-5, 18, 257, -14},
	{-3, 10, 258, -9},
	{-1, 3, 257, -3}
};


int sc_coe1[ID_MAX][SC_INDEX_MAX] = {
	{60, 128, 60, 8},
	{57, 128, 63, 8},
	{54, 128, 66, 8},
	{52, 126, 69, 9},
	{49, 126, 71, 10},
	{47, 125, 74, 10},
	{44, 124, 77, 11},
	{41, 123, 80, 12},
	{39, 121, 83, 13},
	{36, 120, 86, 14},
	{34, 118, 89, 15},
	{32, 116, 91, 17},
	{30, 114, 95, 17},
	{28, 112, 98, 18},
	{26, 110, 100, 20},
	{24, 107, 103, 22},
	{23, 105, 105, 23},
	{21, 102, 108, 25},
	{20, 100, 110, 26},
	{18, 97, 112, 29},
	{17, 94, 114, 31},
	{16, 92, 116, 32},
	{15, 89, 118, 34},
	{13, 86, 121, 36},
	{12, 83, 122, 39},
	{11, 80, 124, 41},
	{10, 77, 125, 44},
	{10, 74, 126, 46},
	{9, 71, 127, 49},
	{8, 69, 128, 51},
	{7, 66, 129, 54},
	{7, 63, 129, 57}
};

int sinc_coe[ID_MAX][SINC_INDEX_MAX] = {
	{5, 12, 31, 50, 60, 50, 31, 12, 5},
	{4, 12, 31, 51, 60, 51, 31, 12, 4},
	{4, 12, 31, 51, 60, 51, 31, 12, 4},
	{3, 11, 31, 52, 62, 52, 31, 11, 3},
	{3, 10, 30, 53, 64, 53, 30, 10, 3},
	{2, 9, 29, 55, 66, 55, 29, 9, 2},
	{1, 7, 28, 57, 70, 57, 28, 7, 1},
	{0, 5, 27, 59, 74, 59, 27, 5, 0},
	{-1, 4, 25, 61, 78, 61, 25, 4, -1},
	{-1, 2, 22, 63, 84, 63, 22, 2, -1},
	{-1, 0, 21, 64, 88, 64, 21, 0, -1},
	{-2, -1, 18, 66, 94, 66, 18, -1, -2},
	{-2, -3, 15, 67, 102, 67, 15, -3, -2},
	{-1, -4, 11, 68, 108, 68, 11, -4, -1},
	{-1, -5, 7, 70, 114, 70, 7, -5, -1},
	{0, -6, 3, 70, 122, 70, 3, -6, 0},
	{0, -6, -2, 71, 130, 71, -2, -6, 0},
	{1, -5, -6, 69, 138, 69, -6, -5, 1},
	{1, -4, -10, 68, 146, 68, -10, -4, 1},
	{2, -3, -13, 66, 152, 66, -13, -3, 2},
	{2, -2, -16, 64, 160, 64, -16, -2, 2},
	{1, 0, -19, 61, 170, 61, -19, 0, 1},
	{1, 2, -21, 57, 178, 57, -21, 2, 1},
	{0, 3, -22, 53, 188, 53, -22, 3, 0},
	{0, 5, -22, 48, 194, 48, -22, 5, 0},
	{-1, 5, -21, 43, 204, 43, -21, 5, -1},
	{-1, 6, -20, 37, 212, 37, -20, 6, -1},
	{-2, 6, -18, 32, 220, 32, -18, 6, -2},
	{-2, 5, -15, 26, 228, 26, -15, 5, -2},
	{-1, 4, -11, 18, 236, 18, -11, 4, -1},
	{-1, 3, -7, 11, 244, 11, -7, 3, -1},
	{0, 1, -1, 2, 252, 2, -1, 1, 0}
};

int GenerateComplement(int val, uint32_t len)
{
	uint32_t i = 0;
	int result = 0;
	u8 temp;
	uint32_t abs_val = abs(val);

	if (val >= 0)
		return val;


	for (i = 0; i < len; i++) {
		temp = abs_val & 0x01;
		if (temp)
			result |= 0 << i;
		else
			result |= 1 << i;

		abs_val = abs_val >> 1;
	}

	return result + 1;
}

void bt1120rx_ConfigScCoe(u16 scMultiple)
{
	uint32_t SC_COE[32][2] = {0};

	if ((scMultiple >= 0) && (scMultiple <= 4)) {
		SC_COE[0][0] = (GenerateComplement(sc_coe0[0][0], 9) << 0)
			| (sc_coe0[0][1] << 16);
		WriteReg32(&rx->sc_coe[0][0], SC_COE[0][0]);

		SC_COE[0][1] = (sc_coe0[0][2] << 0)
			| (GenerateComplement(sc_coe0[0][3], 9) << 16);
		WriteReg32(&rx->sc_coe[0][1], SC_COE[0][1]);

		SC_COE[1][0] = (GenerateComplement(sc_coe0[1][0], 9) << 0)
			| (sc_coe0[1][1] << 16);
		WriteReg32(&rx->sc_coe[1][0], SC_COE[1][0]);

		SC_COE[1][1] = (sc_coe0[1][2] << 0)
			| (GenerateComplement(sc_coe0[1][3], 9) << 16);
		WriteReg32(&rx->sc_coe[1][1], SC_COE[1][1]);

		SC_COE[2][0] = (GenerateComplement(sc_coe0[2][0], 9) << 0)
			| (sc_coe0[2][1] << 16);
		WriteReg32(&rx->sc_coe[2][0], SC_COE[2][0]);

		SC_COE[2][1] = (sc_coe0[2][2] << 0)
			| (GenerateComplement(sc_coe0[2][3], 9) << 16);
		WriteReg32(&rx->sc_coe[2][1], SC_COE[2][1]);

		SC_COE[3][0] = (GenerateComplement(sc_coe0[3][0], 9) << 0)
			| (sc_coe0[3][1] << 16);
		WriteReg32(&rx->sc_coe[3][0], SC_COE[3][0]);

		SC_COE[3][1] = (sc_coe0[3][2] << 0)
			| (GenerateComplement(sc_coe0[3][3], 9) << 16);
		WriteReg32(&rx->sc_coe[3][1], SC_COE[3][1]);

		SC_COE[4][0] = (GenerateComplement(sc_coe0[4][0], 9) << 0)
			| (sc_coe0[4][1] << 16);
		WriteReg32(&rx->sc_coe[4][0], SC_COE[4][0]);

		SC_COE[4][1] = (sc_coe0[4][2] << 0)
			| (GenerateComplement(sc_coe0[4][3], 9) << 16);
		WriteReg32(&rx->sc_coe[4][1], SC_COE[4][1]);

		SC_COE[5][0] = (GenerateComplement(sc_coe0[5][0], 9) << 0)
			| (sc_coe0[5][1] << 16);
		WriteReg32(&rx->sc_coe[5][0], SC_COE[5][0]);

		SC_COE[5][1] = (sc_coe0[5][2] << 0)
			| (GenerateComplement(sc_coe0[5][3], 9) << 16);
		WriteReg32(&rx->sc_coe[5][1], SC_COE[5][1]);

		SC_COE[6][0] = (GenerateComplement(sc_coe0[6][0], 9) << 0)
			| (sc_coe0[6][1] << 16);
		WriteReg32(&rx->sc_coe[6][0], SC_COE[6][0]);

		SC_COE[6][1] = (sc_coe0[6][2] << 0)
			| (GenerateComplement(sc_coe0[6][3], 9) << 16);
		WriteReg32(&rx->sc_coe[6][1], SC_COE[6][1]);

		SC_COE[7][0] = (GenerateComplement(sc_coe0[7][0], 9) << 0)
			| (sc_coe0[7][1] << 16);
		WriteReg32(&rx->sc_coe[7][0], SC_COE[7][0]);

		SC_COE[7][1] = (sc_coe0[7][2] << 0)
			| (GenerateComplement(sc_coe0[7][3], 9) << 16);
		WriteReg32(&rx->sc_coe[7][1], SC_COE[7][1]);

		SC_COE[8][0] = (GenerateComplement(sc_coe0[8][0], 9) << 0)
			| (sc_coe0[8][1] << 16);
		WriteReg32(&rx->sc_coe[8][0], SC_COE[8][0]);

		SC_COE[8][1] = (sc_coe0[8][2] << 0)
			| (GenerateComplement(sc_coe0[8][3], 9) << 16);
		WriteReg32(&rx->sc_coe[8][1], SC_COE[8][1]);

		SC_COE[9][0] = (GenerateComplement(sc_coe0[9][0], 9) << 0)
			| (sc_coe0[9][1] << 16);
		WriteReg32(&rx->sc_coe[9][0], SC_COE[9][0]);

		SC_COE[9][1] = (sc_coe0[9][2] << 0)
			| (GenerateComplement(sc_coe0[9][3], 9) << 16);
		WriteReg32(&rx->sc_coe[9][1], SC_COE[9][1]);

		SC_COE[10][0] = (GenerateComplement(sc_coe0[10][0], 9) << 0)
			| (sc_coe0[10][1] << 16);
		WriteReg32(&rx->sc_coe[10][0], SC_COE[10][0]);

		SC_COE[10][1] = (sc_coe0[10][2] << 0)
			| (GenerateComplement(sc_coe0[10][3], 9) << 16);
		WriteReg32(&rx->sc_coe[10][1], SC_COE[10][1]);

		SC_COE[11][0] = (GenerateComplement(sc_coe0[11][0], 9) << 0)
			| (sc_coe0[11][1] << 16);
		WriteReg32(&rx->sc_coe[11][0], SC_COE[11][0]);

		SC_COE[11][1] = (sc_coe0[11][2] << 0)
			| (GenerateComplement(sc_coe0[11][3], 9) << 16);
		WriteReg32(&rx->sc_coe[11][1], SC_COE[11][1]);

		SC_COE[12][0] = (GenerateComplement(sc_coe0[12][0], 9) << 0)
			| (sc_coe0[12][1] << 16);
		WriteReg32(&rx->sc_coe[12][0], SC_COE[12][0]);

		SC_COE[12][1] = (sc_coe0[12][2] << 0)
			| (GenerateComplement(sc_coe0[12][3], 9) << 16);
		WriteReg32(&rx->sc_coe[12][1], SC_COE[12][1]);

		SC_COE[13][0] = (GenerateComplement(sc_coe0[13][0], 9) << 0)
			| (sc_coe0[13][1] << 16);
		WriteReg32(&rx->sc_coe[13][0], SC_COE[13][0]);

		SC_COE[13][1] = (sc_coe0[13][2] << 0)
			| (GenerateComplement(sc_coe0[13][3], 9) << 16);
		WriteReg32(&rx->sc_coe[13][1], SC_COE[13][1]);

		SC_COE[14][0] = (GenerateComplement(sc_coe0[14][0], 9) << 0)
			| (sc_coe0[14][1] << 16);
		WriteReg32(&rx->sc_coe[14][0], SC_COE[14][0]);

		SC_COE[14][1] = (sc_coe0[14][2] << 0)
			| (GenerateComplement(sc_coe0[14][3], 9) << 16);
		WriteReg32(&rx->sc_coe[14][1], SC_COE[14][1]);

		SC_COE[15][0] = (GenerateComplement(sc_coe0[15][0], 9) << 0)
			| (sc_coe0[15][1] << 16);
		WriteReg32(&rx->sc_coe[15][0], SC_COE[15][0]);

		SC_COE[15][1] = (sc_coe0[15][2] << 0)
			| (GenerateComplement(sc_coe0[15][3], 9) << 16);
		WriteReg32(&rx->sc_coe[15][1], SC_COE[15][1]);

		SC_COE[16][0] = (GenerateComplement(sc_coe0[16][0], 9) << 0)
			| (sc_coe0[16][1] << 16);
		WriteReg32(&rx->sc_coe[16][0], SC_COE[16][0]);

		SC_COE[16][1] = (sc_coe0[16][2] << 0)
			| (GenerateComplement(sc_coe0[16][3], 9) << 16);
		WriteReg32(&rx->sc_coe[16][1], SC_COE[16][1]);

		SC_COE[17][0] = (GenerateComplement(sc_coe0[17][0], 9) << 0)
			| (sc_coe0[17][1] << 16);
		WriteReg32(&rx->sc_coe[17][0], SC_COE[17][0]);

		SC_COE[17][1] = (sc_coe0[17][2] << 0)
			| (GenerateComplement(sc_coe0[17][3], 9) << 16);
		WriteReg32(&rx->sc_coe[17][1], SC_COE[17][1]);

		SC_COE[18][0] = (GenerateComplement(sc_coe0[18][0], 9) << 0)
			| (sc_coe0[18][1] << 16);
		WriteReg32(&rx->sc_coe[18][0], SC_COE[18][0]);

		SC_COE[18][1] = (sc_coe0[18][2] << 0)
			| (GenerateComplement(sc_coe0[18][3], 9) << 16);
		WriteReg32(&rx->sc_coe[18][1], SC_COE[18][1]);

		SC_COE[19][0] = (GenerateComplement(sc_coe0[19][0], 9) << 0)
			| (sc_coe0[19][1] << 16);
		WriteReg32(&rx->sc_coe[19][0], SC_COE[19][0]);

		SC_COE[19][1] = (sc_coe0[19][2] << 0)
			| (GenerateComplement(sc_coe0[19][3], 9) << 16);
		WriteReg32(&rx->sc_coe[19][1], SC_COE[19][1]);

		SC_COE[20][0] = (GenerateComplement(sc_coe0[20][0], 9) << 0)
			| (sc_coe0[20][1] << 16);
		WriteReg32(&rx->sc_coe[20][0], SC_COE[20][0]);

		SC_COE[20][1] = (sc_coe0[20][2] << 0)
			| (GenerateComplement(sc_coe0[20][3], 9) << 16);
		WriteReg32(&rx->sc_coe[20][1], SC_COE[20][1]);

		SC_COE[21][0] = (GenerateComplement(sc_coe0[21][0], 9) << 0)
			| (sc_coe0[21][1] << 16);
		WriteReg32(&rx->sc_coe[21][0], SC_COE[21][0]);

		SC_COE[21][1] = (sc_coe0[21][2] << 0)
			| (GenerateComplement(sc_coe0[21][3], 9) << 16);
		WriteReg32(&rx->sc_coe[21][1], SC_COE[21][1]);

		SC_COE[22][0] = (GenerateComplement(sc_coe0[22][0], 9) << 0)
			| (sc_coe0[22][1] << 16);
		WriteReg32(&rx->sc_coe[22][0], SC_COE[22][0]);

		SC_COE[22][1] = (sc_coe0[22][2] << 0)
			| (GenerateComplement(sc_coe0[22][3], 9) << 16);
		WriteReg32(&rx->sc_coe[22][1], SC_COE[22][1]);

		SC_COE[23][0] = (GenerateComplement(sc_coe0[23][0], 9) << 0)
			| (sc_coe0[23][1] << 16);
		WriteReg32(&rx->sc_coe[23][0], SC_COE[23][0]);

		SC_COE[23][1] = (sc_coe0[23][2] << 0)
			| (GenerateComplement(sc_coe0[23][3], 9) << 16);
		WriteReg32(&rx->sc_coe[23][1], SC_COE[23][1]);

		SC_COE[24][0] = (GenerateComplement(sc_coe0[24][0], 9) << 0)
			| (sc_coe0[24][1] << 16);
		WriteReg32(&rx->sc_coe[24][0], SC_COE[24][0]);

		SC_COE[24][1] = (sc_coe0[24][2] << 0)
			| (GenerateComplement(sc_coe0[24][3], 9) << 16);
		WriteReg32(&rx->sc_coe[24][1], SC_COE[24][1]);

		SC_COE[25][0] = (GenerateComplement(sc_coe0[25][0], 9) << 0)
			| (sc_coe0[25][1] << 16);
		WriteReg32(&rx->sc_coe[25][0], SC_COE[25][0]);

		SC_COE[25][1] = (sc_coe0[25][2] << 0)
			| (GenerateComplement(sc_coe0[25][3], 9) << 16);
		WriteReg32(&rx->sc_coe[25][1], SC_COE[25][1]);

		SC_COE[26][0] = (GenerateComplement(sc_coe0[26][0], 9) << 0)
			| (sc_coe0[26][1] << 16);
		WriteReg32(&rx->sc_coe[26][0], SC_COE[26][0]);

		SC_COE[26][1] = (sc_coe0[26][2] << 0)
			| (GenerateComplement(sc_coe0[26][3], 9) << 16);
		WriteReg32(&rx->sc_coe[26][1], SC_COE[26][1]);

		SC_COE[27][0] = (GenerateComplement(sc_coe0[27][0], 9) << 0)
			| (sc_coe0[27][1] << 16);
		WriteReg32(&rx->sc_coe[27][0], SC_COE[27][0]);

		SC_COE[27][1] = (sc_coe0[27][2] << 0)
			| (GenerateComplement(sc_coe0[27][3], 9) << 16);
		WriteReg32(&rx->sc_coe[27][1], SC_COE[27][1]);

		SC_COE[28][0] = (GenerateComplement(sc_coe0[28][0], 9) << 0)
			| (sc_coe0[28][1] << 16);
		WriteReg32(&rx->sc_coe[28][0], SC_COE[28][0]);

		SC_COE[28][1] = (sc_coe0[28][2] << 0)
			| (GenerateComplement(sc_coe0[28][3], 9) << 16);
		WriteReg32(&rx->sc_coe[28][1], SC_COE[28][1]);

		SC_COE[29][0] = (GenerateComplement(sc_coe0[29][0], 9) << 0)
			| (sc_coe0[29][1] << 16);
		WriteReg32(&rx->sc_coe[29][0], SC_COE[29][0]);

		SC_COE[29][1] = (sc_coe0[29][2] << 0)
			| (GenerateComplement(sc_coe0[29][3], 9) << 16);
		WriteReg32(&rx->sc_coe[29][1], SC_COE[29][1]);

		SC_COE[30][0] = (GenerateComplement(sc_coe0[30][0], 9) << 0)
			| (sc_coe0[30][1] << 16);
		WriteReg32(&rx->sc_coe[30][0], SC_COE[30][0]);

		SC_COE[30][1] = (sc_coe0[30][2] << 0)
			| (GenerateComplement(sc_coe0[30][3], 9) << 16);
		WriteReg32(&rx->sc_coe[30][1], SC_COE[30][1]);

		SC_COE[31][0] = (GenerateComplement(sc_coe0[31][0], 9) << 0)
			| (sc_coe0[31][1] << 16);
		WriteReg32(&rx->sc_coe[31][0], SC_COE[31][0]);

		SC_COE[31][1] = (sc_coe0[31][2] << 0)
			| (GenerateComplement(sc_coe0[31][3], 9) << 16);
		WriteReg32(&rx->sc_coe[31][1], SC_COE[31][1]);
	} else {

		SC_COE[0][0] = (sc_coe1[0][0] << 0) | (sc_coe1[0][1] << 16);
		WriteReg32(&rx->sc_coe[0][0], SC_COE[0][0]);

		SC_COE[0][1] = (sc_coe1[0][2] << 0) | (sc_coe1[0][3] << 16);
		WriteReg32(&rx->sc_coe[0][1], SC_COE[0][1]);

		SC_COE[1][0] = (sc_coe1[1][0] << 0) | (sc_coe1[1][1] << 16);
		WriteReg32(&rx->sc_coe[1][0], SC_COE[1][0]);

		SC_COE[1][1] = (sc_coe1[1][2] << 0) | (sc_coe1[1][3] << 16);
		WriteReg32(&rx->sc_coe[1][1], SC_COE[1][1]);

		SC_COE[2][0] = (sc_coe1[2][0] << 0) | (sc_coe1[2][1] << 16);
		WriteReg32(&rx->sc_coe[2][0], SC_COE[2][0]);

		SC_COE[2][1] = (sc_coe1[2][2] << 0) | (sc_coe1[2][3] << 16);
		WriteReg32(&rx->sc_coe[2][1], SC_COE[2][1]);

		SC_COE[3][0] = (sc_coe1[3][0] << 0) | (sc_coe1[3][1] << 16);
		WriteReg32(&rx->sc_coe[3][0], SC_COE[3][0]);

		SC_COE[3][1] = (sc_coe1[3][2] << 0) | (sc_coe1[3][3] << 16);
		WriteReg32(&rx->sc_coe[3][1], SC_COE[3][1]);

		SC_COE[4][0] = (sc_coe1[4][0] << 0) | (sc_coe1[4][1] << 16);
		WriteReg32(&rx->sc_coe[4][0], SC_COE[4][0]);

		SC_COE[4][1] = (sc_coe1[4][2] << 0) | (sc_coe1[4][3] << 16);
		WriteReg32(&rx->sc_coe[4][1], SC_COE[4][1]);

		SC_COE[5][0] = (sc_coe1[5][0] << 0) | (sc_coe1[5][1] << 16);
		WriteReg32(&rx->sc_coe[5][0], SC_COE[5][0]);

		SC_COE[5][1] = (sc_coe1[5][2] << 0) | (sc_coe1[5][3] << 16);
		WriteReg32(&rx->sc_coe[5][1], SC_COE[5][1]);

		SC_COE[6][0] = (sc_coe1[6][0] << 0) | (sc_coe1[6][1] << 16);
		WriteReg32(&rx->sc_coe[6][0], SC_COE[6][0]);

		SC_COE[6][1] = (sc_coe1[6][2] << 0) | (sc_coe1[6][3] << 16);
		WriteReg32(&rx->sc_coe[6][1], SC_COE[6][1]);

		SC_COE[7][0] = (sc_coe1[7][0] << 0) | (sc_coe1[7][1] << 16);
		WriteReg32(&rx->sc_coe[7][0], SC_COE[7][0]);

		SC_COE[7][1] = (sc_coe1[7][2] << 0) | (sc_coe1[7][3] << 16);
		WriteReg32(&rx->sc_coe[7][1], SC_COE[7][1]);

		SC_COE[8][0] = (sc_coe1[8][0] << 0) | (sc_coe1[8][1] << 16);
		WriteReg32(&rx->sc_coe[8][0], SC_COE[8][0]);

		SC_COE[8][1] = (sc_coe1[8][2] << 0) | (sc_coe1[8][3] << 16);
		WriteReg32(&rx->sc_coe[8][1], SC_COE[8][1]);

		SC_COE[9][0] = (sc_coe1[9][0] << 0) | (sc_coe1[9][1] << 16);
		WriteReg32(&rx->sc_coe[9][0], SC_COE[9][0]);

		SC_COE[9][1] = (sc_coe1[9][2] << 0) | (sc_coe1[9][3] << 16);
		WriteReg32(&rx->sc_coe[9][1], SC_COE[9][1]);

		SC_COE[10][0] = (sc_coe1[10][0] << 0) | (sc_coe1[10][1] << 16);
		WriteReg32(&rx->sc_coe[10][0], SC_COE[10][0]);

		SC_COE[10][1] = (sc_coe1[10][2] << 0) | (sc_coe1[10][3] << 16);
		WriteReg32(&rx->sc_coe[10][1], SC_COE[10][1]);

		SC_COE[11][0] = (sc_coe1[11][0] << 0) | (sc_coe1[11][1] << 16);
		WriteReg32(&rx->sc_coe[11][0], SC_COE[11][0]);

		SC_COE[11][1] = (sc_coe1[11][2] << 0) | (sc_coe1[11][3] << 16);
		WriteReg32(&rx->sc_coe[11][1], SC_COE[11][1]);

		SC_COE[12][0] = (sc_coe1[12][0] << 0) | (sc_coe1[12][1] << 16);
		WriteReg32(&rx->sc_coe[12][0], SC_COE[12][0]);

		SC_COE[12][1] = (sc_coe1[12][2] << 0) | (sc_coe1[12][3] << 16);
		WriteReg32(&rx->sc_coe[12][1], SC_COE[12][1]);

		SC_COE[13][0] = (sc_coe1[13][0] << 0) | (sc_coe1[13][1] << 16);
		WriteReg32(&rx->sc_coe[13][0], SC_COE[13][0]);

		SC_COE[13][1] = (sc_coe1[13][2] << 0) | (sc_coe1[13][3] << 16);
		WriteReg32(&rx->sc_coe[13][1], SC_COE[13][1]);

		SC_COE[14][0] = (sc_coe1[14][0] << 0) | (sc_coe1[14][1] << 16);
		WriteReg32(&rx->sc_coe[14][0], SC_COE[14][0]);

		SC_COE[14][1] = (sc_coe1[14][2] << 0) | (sc_coe1[14][3] << 16);
		WriteReg32(&rx->sc_coe[14][1], SC_COE[14][1]);

		SC_COE[15][0] = (sc_coe1[15][0] << 0) | (sc_coe1[15][1] << 16);
		WriteReg32(&rx->sc_coe[15][0], SC_COE[15][0]);

		SC_COE[15][1] = (sc_coe1[15][2] << 0) | (sc_coe1[15][3] << 16);
		WriteReg32(&rx->sc_coe[15][1], SC_COE[15][1]);

		SC_COE[16][0] = (sc_coe1[16][0] << 0) | (sc_coe1[16][1] << 16);
		WriteReg32(&rx->sc_coe[16][0], SC_COE[16][0]);

		SC_COE[16][1] = (sc_coe1[16][2] << 0) | (sc_coe1[16][3] << 16);
		WriteReg32(&rx->sc_coe[16][1], SC_COE[16][1]);

		SC_COE[17][0] = (sc_coe1[17][0] << 0) | (sc_coe1[17][1] << 16);
		WriteReg32(&rx->sc_coe[17][0], SC_COE[17][0]);

		SC_COE[17][1] = (sc_coe1[17][2] << 0) | (sc_coe1[17][3] << 16);
		WriteReg32(&rx->sc_coe[17][1], SC_COE[17][1]);

		SC_COE[18][0] = (sc_coe1[18][0] << 0) | (sc_coe1[18][1] << 16);
		WriteReg32(&rx->sc_coe[18][0], SC_COE[18][0]);

		SC_COE[18][1] = (sc_coe1[18][2] << 0) | (sc_coe1[18][3] << 16);
		WriteReg32(&rx->sc_coe[18][1], SC_COE[18][1]);

		SC_COE[19][0] = (sc_coe1[19][0] << 0) | (sc_coe1[19][1] << 16);
		WriteReg32(&rx->sc_coe[19][0], SC_COE[19][0]);

		SC_COE[19][1] = (sc_coe1[19][2] << 0) | (sc_coe1[19][3] << 16);
		WriteReg32(&rx->sc_coe[19][1], SC_COE[19][1]);

		SC_COE[20][0] = (sc_coe1[20][0] << 0) | (sc_coe1[20][1] << 16);
		WriteReg32(&rx->sc_coe[20][0], SC_COE[20][0]);

		SC_COE[20][1] = (sc_coe1[20][2] << 0) | (sc_coe1[20][3] << 16);
		WriteReg32(&rx->sc_coe[20][1], SC_COE[20][1]);

		SC_COE[21][0] = (sc_coe1[21][0] << 0) | (sc_coe1[21][1] << 16);
		WriteReg32(&rx->sc_coe[21][0], SC_COE[21][0]);

		SC_COE[21][1] = (sc_coe1[21][2] << 0) | (sc_coe1[21][3] << 16);
		WriteReg32(&rx->sc_coe[21][1], SC_COE[21][1]);

		SC_COE[22][0] = (sc_coe1[22][0] << 0) | (sc_coe1[22][1] << 16);
		WriteReg32(&rx->sc_coe[22][0], SC_COE[22][0]);

		SC_COE[22][1] = (sc_coe1[22][2] << 0) | (sc_coe1[22][3] << 16);
		WriteReg32(&rx->sc_coe[22][1], SC_COE[22][1]);

		SC_COE[23][0] = (sc_coe1[23][0] << 0) | (sc_coe1[23][1] << 16);
		WriteReg32(&rx->sc_coe[23][0], SC_COE[23][0]);

		SC_COE[23][1] = (sc_coe1[23][2] << 0) | (sc_coe1[23][3] << 16);
		WriteReg32(&rx->sc_coe[23][1], SC_COE[23][1]);

		SC_COE[24][0] = (sc_coe1[24][0] << 0) | (sc_coe1[24][1] << 16);
		WriteReg32(&rx->sc_coe[24][0], SC_COE[24][0]);

		SC_COE[24][1] = (sc_coe1[24][2] << 0) | (sc_coe1[24][3] << 16);
		WriteReg32(&rx->sc_coe[24][1], SC_COE[24][1]);

		SC_COE[25][0] = (sc_coe1[25][0] << 0) | (sc_coe1[25][1] << 16);
		WriteReg32(&rx->sc_coe[25][0], SC_COE[25][0]);

		SC_COE[25][1] = (sc_coe1[25][2] << 0) | (sc_coe1[25][3] << 16);
		WriteReg32(&rx->sc_coe[25][1], SC_COE[25][1]);

		SC_COE[26][0] = (sc_coe1[26][0] << 0) | (sc_coe1[26][1] << 16);
		WriteReg32(&rx->sc_coe[26][0], SC_COE[26][0]);

		SC_COE[26][1] = (sc_coe1[26][2] << 0) | (sc_coe1[26][3] << 16);
		WriteReg32(&rx->sc_coe[26][1], SC_COE[26][1]);

		SC_COE[27][0] = (sc_coe1[27][0] << 0) | (sc_coe1[27][1] << 16);
		WriteReg32(&rx->sc_coe[27][0], SC_COE[27][0]);

		SC_COE[27][1] = (sc_coe1[27][2] << 0) | (sc_coe1[27][3] << 16);
		WriteReg32(&rx->sc_coe[27][1], SC_COE[27][1]);

		SC_COE[28][0] = (sc_coe1[28][0] << 0) | (sc_coe1[28][1] << 16);
		WriteReg32(&rx->sc_coe[28][0], SC_COE[28][0]);

		SC_COE[28][1] = (sc_coe1[28][2] << 0) | (sc_coe1[28][3] << 16);
		WriteReg32(&rx->sc_coe[28][1], SC_COE[28][1]);

		SC_COE[29][0] = (sc_coe1[29][0] << 0) | (sc_coe1[29][1] << 16);
		WriteReg32(&rx->sc_coe[29][0], SC_COE[29][0]);

		SC_COE[29][1] = (sc_coe1[29][2] << 0) | (sc_coe1[29][3] << 16);
		WriteReg32(&rx->sc_coe[29][1], SC_COE[29][1]);

		SC_COE[30][0] = (sc_coe1[30][0] << 0) | (sc_coe1[30][1] << 16);
		WriteReg32(&rx->sc_coe[30][0], SC_COE[30][0]);

		SC_COE[30][1] = (sc_coe1[30][2] << 0) | (sc_coe1[30][3] << 16);
		WriteReg32(&rx->sc_coe[30][1], SC_COE[30][1]);

		SC_COE[31][0] = (sc_coe1[31][0] << 0) | (sc_coe1[31][1] << 16);
		WriteReg32(&rx->sc_coe[31][0], SC_COE[31][0]);

		SC_COE[31][1] = (sc_coe1[31][2] << 0) | (sc_coe1[31][3] << 16);
		WriteReg32(&rx->sc_coe[31][1], SC_COE[31][1]);
	}
	bt_debug(2, "%p: 0x%08x : scaling coe configure.\r\n",
		&rx->sc_coe[31][1], SC_COE[31][1]);
}

void bt1120rx_ConfigSincHzCoe(u16 hzArrayIdx)
{
	unsigned int SINC_HZ_Y_COE0, SINC_HZ_Y_COE1,
		SINC_HZ_UV_COE0, SINC_HZ_UV_COE1;

	SINC_HZ_Y_COE0 =
		(GenerateComplement(sinc_coe[hzArrayIdx][0], 9) << 18) |
		(GenerateComplement(sinc_coe[hzArrayIdx][1], 9) << 9) |
		(GenerateComplement(sinc_coe[hzArrayIdx][2], 9) << 0);
	WriteReg32(&rx->sinc_hz_y_coe0, SINC_HZ_Y_COE0);
	SINC_HZ_Y_COE1 =
		(GenerateComplement(sinc_coe[hzArrayIdx][3], 9) << 9) |
		(GenerateComplement(sinc_coe[hzArrayIdx][4], 9) << 0);
	WriteReg32(&rx->sinc_hz_y_coe1, SINC_HZ_Y_COE1);
	SINC_HZ_UV_COE0 =
		(GenerateComplement(sinc_coe[hzArrayIdx][0], 9) << 18) |
		(GenerateComplement(sinc_coe[hzArrayIdx][1], 9) << 9) |
		(GenerateComplement(sinc_coe[hzArrayIdx][2], 9) << 0);
	WriteReg32(&rx->sinc_hz_uv_coe0, SINC_HZ_UV_COE0);
	SINC_HZ_UV_COE1 =
		(GenerateComplement(sinc_coe[hzArrayIdx][3], 9) << 9) |
		(GenerateComplement(sinc_coe[hzArrayIdx][4], 9) << 0);
	WriteReg32(&rx->sinc_hz_uv_coe1, SINC_HZ_UV_COE1);

	bt_debug(2, "%p: 0x%08x : sinc_hz_coe configure.\r\n",
				 &rx->sinc_hz_uv_coe1, SINC_HZ_UV_COE1);
}

void bt1120rx_ConfigSincVtCoe(u16 vtArrayIdx)
{
	unsigned int SINC_VT_Y_COE0, SINC_VT_Y_COE1,
		SINC_VT_UV_COE0, SINC_VT_UV_COE1;

	SINC_VT_Y_COE0 =
		(GenerateComplement(sinc_coe[vtArrayIdx][0], 9) << 18) |
		(GenerateComplement(sinc_coe[vtArrayIdx][1], 9) << 9) |
		(GenerateComplement(sinc_coe[vtArrayIdx][2], 9) << 0);
	WriteReg32(&rx->sinc_vt_y_coe0 /* 0x124 */, SINC_VT_Y_COE0);
	SINC_VT_Y_COE1 =
		(GenerateComplement(sinc_coe[vtArrayIdx][3], 9) << 9) |
		(GenerateComplement(sinc_coe[vtArrayIdx][4], 9) << 0);
	WriteReg32(&rx->sinc_vt_y_coe1, SINC_VT_Y_COE1);
	SINC_VT_UV_COE0 =
		(GenerateComplement(sinc_coe[vtArrayIdx][0], 9) << 18)
		| (GenerateComplement(sinc_coe[vtArrayIdx][1], 9) << 9)
		| (GenerateComplement(sinc_coe[vtArrayIdx][2], 9) << 0);
	WriteReg32(&rx->sinc_vt_uv_coe0, SINC_VT_UV_COE0);
	SINC_VT_UV_COE1 =
		(GenerateComplement(sinc_coe[vtArrayIdx][3], 9) << 9) |
		(GenerateComplement(sinc_coe[vtArrayIdx][4], 9) << 0);
	WriteReg32(&rx->sinc_vt_uv_coe1 /* 0x130 */, SINC_VT_UV_COE1);

	bt_debug(2, "%p: 0x%08x : sinc_vt_uv_coe configure.\r\n",
		&rx->sinc_vt_uv_coe1, SINC_VT_UV_COE1);
}

void bt1120rx_EnSc(sc_en *scEn)
{
	uint32_t sc_en = (scEn->sc_vt_en << SC_VT_EN_BIT)
					| (scEn->sc_hz_en << SC_HZ_EN_BIT);

	WriteReg32(&rx->sc_en /* 0x11c */, sc_en);
}

void bt1120rx_EnSinc(sinc_en *sincEn)
{
	uint32_t sinc_en = (sincEn->vt_y_en << SINC_VT_Y_EN) |
				 (sincEn->vt_uv_en << SINC_VT_UV_EN) |
				 (sincEn->hz_y_en << SINC_HZ_Y_EN) |
				 (sincEn->hz_uv_en << SINC_HZ_UV_EN);
	WriteReg32(&rx->sinc_en /* 0x118 */, sinc_en);
}


void bt1120rx_ConfigScaling(bt1120rx_Config *rxCfg,  bt1120_Rx_Regs *rx)
{
	uint32_t sc_image_info_val, scale_ratiok_hz, scale_ratiok_vt;

	if (rxCfg->dst_width > rxCfg->src_width)
		rxCfg->dst_width = rxCfg->src_width;

	if (rxCfg->dst_height > rxCfg->src_height)
		rxCfg->dst_height = rxCfg->src_height;

	rxCfg->sc_image_info.sc_width =
		rxCfg->dst_width = rxCfg->dst_width & 0xFFFE;
	rxCfg->sc_image_info.sc_height =
		rxCfg->dst_height = rxCfg->dst_height & 0xFFFE;

	sc_image_info_val = rxCfg->sc_image_info.sc_width |
		rxCfg->sc_image_info.sc_height << 16;
	WriteReg32(&rx->sc_image_info, sc_image_info_val);
	bt_debug(2, "%p: 0x%08x : sc_image_info width height.\r\n",
		&rx->sc_image_info, sc_image_info_val);

	scale_ratiok_hz = rxCfg->video_config.bt1120_width_vld *
		65536 / rxCfg->sc_image_info.sc_width;

	WriteReg32(&rx->scale_ratiok_hz, scale_ratiok_hz);

	scale_ratiok_vt = rxCfg->video_config.bt1120_height_vld *
		65536 / rxCfg->sc_image_info.sc_height;

	WriteReg32(&rx->scale_ratiok_vt, scale_ratiok_vt);

	//static sc_en scEn;
	//static sinc_en sincEn;

	if ((rxCfg->dst_width == rxCfg->src_width) &&
			 (rxCfg->dst_height == rxCfg->src_height)) {
		rxCfg->sinc_en.vt_y_en = VT_Y_DIS;
		rxCfg->sinc_en.vt_uv_en = VT_UV_DIS;
		rxCfg->sinc_en.hz_y_en = HZ_Y_DIS;
		rxCfg->sinc_en.hz_uv_en = HZ_UV_DIS;

		rxCfg->sc_en.sc_vt_en = SC_VT_DIS;
		rxCfg->sc_en.sc_hz_en = SC_HZ_DIS;
	} else {
		if (rxCfg->dst_width < rxCfg->src_width) {
			rxCfg->hz_array_idx =
				 (rxCfg->dst_width * 32) / rxCfg->src_width;
			bt1120rx_ConfigSincHzCoe(rxCfg->hz_array_idx);

			rxCfg->sinc_en.hz_y_en = HZ_Y_EN;
			rxCfg->sinc_en.hz_uv_en = HZ_UV_EN;

			rxCfg->sc_en.sc_hz_en = SC_HZ_EN;
		}

		if (rxCfg->dst_height < rxCfg->src_height) {
			rxCfg->vt_array_idx =
				 (rxCfg->dst_height * 32) / rxCfg->src_height;
			// config sinc
			bt1120rx_ConfigSincVtCoe(rxCfg->vt_array_idx);

			rxCfg->sinc_en.vt_y_en = VT_Y_EN;
			rxCfg->sinc_en.vt_uv_en = VT_UV_EN;

			rxCfg->sc_en.sc_vt_en = SC_VT_EN;
		}

		rxCfg->sc_multiple = rxCfg->src_width / rxCfg->dst_width;
		// config scaling
		bt1120rx_ConfigScCoe(rxCfg->sc_multiple);
	}
	bt1120rx_EnSinc(&rxCfg->sinc_en);		// enable sinc
	bt1120rx_EnSc(&rxCfg->sc_en);			// enable scaling
}

char *pic_format[9] = {
	[0] = "ORGB",
	[1] = "RGB_DIV",
	"",
	"",
	[4] = "UYVY",
	[5] = "YUYV",
	[6] = "IYUV",
	[7] = "YUV4",
	[8] = "U8"
};

void bt1120rx_ConfigGsg(bt1120rx_Config *rxCfg)
{
	uint32_t gsg_k0_val, gsg_k1_val, gsg_k2_val, gsg_k3_val;

	rxCfg->gsg_kr_v = KR_V_DEF_VAL;
	rxCfg->gsg_kr_y = KR_Y_DEF_VAL;
	rxCfg->gsg_kg_u = KG_U_DEF_VAL;
	rxCfg->gsg_kg_y = KG_Y_DEF_VAL;
	rxCfg->gsg_kb_y = KB_Y_DEF_VAL;
	rxCfg->gsg_kg_v = KG_V_DEF_VAL;
	rxCfg->gsg_kb_u = KB_U_DEF_VAL;

	gsg_k0_val = (rxCfg->gsg_kr_v << 16) | (rxCfg->gsg_kr_y << 0);
	gsg_k1_val = (rxCfg->gsg_kg_u << 16) | (rxCfg->gsg_kg_y << 0);
	gsg_k2_val = (rxCfg->gsg_kb_y << 16) | (rxCfg->gsg_kg_v << 0);
	gsg_k3_val = rxCfg->gsg_kb_u;

	WriteReg32(&rx->pic_mode, (uint32_t)rxCfg->pic_mode);
	bt_debug(2, "%p: 0x%08x : pic_mode=%s.\r\n", &rx->pic_mode,
		(uint32_t)rxCfg->pic_mode, pic_format[rxCfg->pic_mode]);

	WriteReg32(&rx->gsgs_k0, gsg_k0_val);
	WriteReg32(&rx->gsgs_k1, gsg_k1_val);
	WriteReg32(&rx->gsgs_k2, gsg_k2_val);
	WriteReg32(&rx->gsgs_k3, gsg_k3_val);
	bt_debug(2, "%p: 0x%08x : gsg configure.\r\n",
		&rx->gsgs_k3, gsg_k3_val);
}

void bt1120rx_video_input_range(bt1120rx_Config *rxCfg)
{
	uint32_t bt1120_range_config_val;

	rxCfg->range_config.bt1120_max_y_set = 0xeb;//0xFF;
	rxCfg->range_config.bt1120_min_y_set = 0x10;//0x00;
	rxCfg->range_config.bt1120_max_c_set = 0xf0;//0xFF;
	rxCfg->range_config.bt1120_min_c_set = 0x10;//0x00;

	bt1120_range_config_val =
				 (rxCfg->range_config.bt1120_max_y_set << 0) |
				 (rxCfg->range_config.bt1120_min_y_set << 8) |
				 (rxCfg->range_config.bt1120_max_c_set << 16) |
				 (rxCfg->range_config.bt1120_min_c_set << 24);

	WriteReg32(&rx->bt1120_range_config, bt1120_range_config_val);
	bt_debug(2, "%p: 0x%08x : video input range configure.\r\n",
		&rx->bt1120_range_config, bt1120_range_config_val);

	rxCfg->vsync_config.bt1120_vsync_delay = VSYNC_DELAY_DEF;

	WriteReg32(&rx->bt1120_vsync_config,
				 rxCfg->vsync_config.bt1120_vsync_delay);
	bt_debug(2, "%p: 0x%08x : video input vsync_delay configure.\r\n",
		&rx->bt1120_vsync_config,
		rxCfg->vsync_config.bt1120_vsync_delay);
}

void bt1120rx_video_input_config(bt1120rx_Config *rxCfg)
{
	uint32_t video_config_val;

	rxCfg->video_config.bt1120_width_vld = rxCfg->src_width;
	rxCfg->video_config.bt1120_height_vld = rxCfg->src_height;
	video_config_val =
		rxCfg->video_config.bt1120_width_vld |
		rxCfg->video_config.bt1120_height_vld << 16;

	WriteReg32(&rx->bt1120_video_config, video_config_val);
	bt_debug(2, "%p: 0x%08x : video input width height configure.\r\n",
			&rx->bt1120_ctrl, video_config_val);
	bt1120rx_video_input_range(rxCfg);
}

void bt1120rx_config_output_video(bt1120rx_Config *rxCfg)
{
	/* read only register ?  */
	if (rxCfg->bt1120_ctrl.bt1120_dec_mode == AUTO_DEC_MODE)
		return;

	if ((rxCfg->dst_width == 1920) && (rxCfg->dst_height == 1080))
		rxCfg->output_info1.bt1120_frame_size = FRAME_SIZE_1080P;
	else if ((rxCfg->dst_width == 1280) && (rxCfg->dst_height == 720))
		rxCfg->output_info1.bt1120_frame_size = FRAME_SIZE_720P;
	else
		rxCfg->output_info1.bt1120_frame_size = FRAME_SIZE_720P;

	WriteReg32(&rx->bt1120_video_info1,
		rxCfg->output_info1.bt1120_frame_size |
		rxCfg->output_info1.bt1120_frame_freq << 8);
		// output resolution

	rxCfg->output_info2.bt1120_img_w_valid = rxCfg->dst_width;
	rxCfg->output_info2.bt1120_img_h_valid = rxCfg->dst_height;

	WriteReg32(&rx->bt1120_video_info2,
		rxCfg->output_info2.bt1120_img_w_valid |
		rxCfg->output_info2.bt1120_img_h_valid << 16);
		// valid data

	rxCfg->output_info3.bt1120_img_w_all = rxCfg->dst_width;
	rxCfg->output_info3.bt1120_img_h_all = rxCfg->dst_height;
	WriteReg32(&rx->bt1120_video_info3,
		rxCfg->output_info3.bt1120_img_w_all |
		rxCfg->output_info3.bt1120_img_h_all << 16);
		// output max resolution
}

char frame_freq[16][8] = {
"25p", "30p", "50p", "60p", "50i", "59.94i",
"12.5p", "15p", "20p", " ", [15] = "custom"
};

char frame_size[16][8] = {"720p", "1080p", [15] = "custom"};

void bt1120rx_video_output_info(bt1120rx_Config *rxCfg,
	bt1120_Rx_Regs *rx)
{
	/* read only register */
	bt1120_video_info1 vinfo1;
	bt1120_video_info2 vinfo2;
	bt1120_video_info3 vinfo3;

	uint32_t info1 = ReadReg32(&rx->bt1120_video_info1);
	uint32_t info2 = ReadReg32(&rx->bt1120_video_info2);
	uint32_t info3 = ReadReg32(&rx->bt1120_video_info3);

	vinfo1.bt1120_frame_size = info1 & 0x0F;
	vinfo1.bt1120_frame_freq = (info1 >> 8) & 0x0F;

	vinfo2.bt1120_img_w_valid = info2 & 0xFFF;
	vinfo2.bt1120_img_h_valid = (info2 >> 16) & 0xFFF;

	vinfo3.bt1120_img_w_all = info3 & 0xFFF;
	vinfo3.bt1120_img_h_all = (info3 >> 16) & 0xFFF;

	rxCfg->output_info1 = vinfo1;
	rxCfg->output_info2 = vinfo2;
	rxCfg->output_info3 = vinfo3;

	bt_debug(2, "video info: %s %s w:%d %d h:%d %d\n",
			 &frame_size[vinfo1.bt1120_frame_size][0],
			 &frame_freq[vinfo1.bt1120_frame_freq][0],
			 vinfo2.bt1120_img_w_valid, vinfo3.bt1120_img_w_all,
			 vinfo2.bt1120_img_h_valid, vinfo3.bt1120_img_h_all);
}

void bt1120rx_dump_y_info(bt1120rx_Config *rxCfg, bt1120_Rx_Regs *rx)
{
	int i, j;

	for (i = 0; i < rxCfg->bank_num; i++) {
		for (j = 0; j < 32; j++) {
			rxCfg->bank_info[i][j] =
				ReadReg32(&rx->bank_info[i][j]);
			bt_debug(2, "0x%08x ", rxCfg->bank_info[i][j]);
		}
		bt_debug(2, "\n\n");
	}
	bt_debug(2, "\n");
}

void bt1120rx_test_status(bt1120rx_Config *rxCfg, bt1120_Rx_Regs *rx)
{
	rxCfg->test_status = ReadReg32(&rx->test_status);

	if (rxCfg->test_status & 0x01)
		bt_debug(2, "Y FIFO overflow!\n");

	if (rxCfg->test_status & 0x10)
		bt_debug(2, "UV FIFO overflow!\n");
}

void bt1120rx_ready_info(bt1120rx_Config *rxCfg, bt1120_Rx_Regs *rx)
{
	uint32_t para0 = ReadReg32(&rx->ready_para0);
	uint32_t para1 = ReadReg32(&rx->ready_para1);
	uint32_t para2 = ReadReg32(&rx->ready_para2);

	uint32_t width =
		 rxCfg->ready_para0.ready_image_width =
		 para0 & 0xFFF;
	uint32_t height =
		 rxCfg->ready_para0.ready_image_height =
		 (para0 >> 12) & 0xFFF;
	uint32_t stride_en =
		 rxCfg->ready_para0.ready_image_stride_en =
		 (para0 >> 24) & 0x07;
	uint32_t mode =
		rxCfg->ready_para0.ready_image_mode =
		para0 >> 28;

	uint32_t stride0 =
		rxCfg->ready_para1.ready_image_stride0 = para1 & 0xFFFF;
	uint32_t stride1 =
		rxCfg->ready_para1.ready_image_stride1 = para1 >> 16;

	uint32_t stride2 =
		rxCfg->ready_para2.ready_image_stride2 = para2 & 0xFFF;

	bt_debug(2,
"ready image mode=%d width=%d height=%d stride_en=%d stride0=%d 1=%d 2=%d\n",
		mode, width, height, stride_en, stride0, stride1, stride2);
}

void bt1120rx_info_extr_enable(bt1120rx_Config *rxCfg)
{
	if (rxCfg->frame_info_extr_en) {
		SETBIT(rxCfg->frame_info_extr_en, FRAME_INFO_EXTRA_ENABLE);
		WriteReg32(&rx->frame_info_extr_en, rxCfg->frame_info_extr_en);
		bt_debug(2, "%p: 0x%08x : frame_info_extr enable.\r\n",
			&rx->frame_info_extr_en, rxCfg->frame_info_extr_en);
	}
}

void bt1120rx_config_bank_addr(bt1120rx_Config *rxCfg)
{
	uint32_t i, plane_size[2] = {0, 0};
	void *addr_base = (void *)(uintptr_t)(DEC_BANK_ADDR_BASE);

	#if defined(__KERNEL__) || 1
	addr_base = (void *)(uintptr_t)rxCfg->dma_handler;
	#endif

	switch (rxCfg->pic_mode) {
	case ORGB:
	case UYVY:
	case YUYV:
	case U8:
		plane_size[0] = 0;
		plane_size[1] = 0;
		break;
	case RGB_DIV:
		plane_size[0] = rxCfg->axi_fmt_stride0.pic_stride0 *
			rxCfg->sc_image_info.sc_height;
		plane_size[1] = rxCfg->axi_fmt_stride1.pic_stride1 *
			rxCfg->sc_image_info.sc_height;
		break;
	case IYUV:
		plane_size[0] = rxCfg->axi_fmt_stride0.pic_stride0 *
			rxCfg->sc_image_info.sc_height;
		plane_size[1] = rxCfg->axi_fmt_stride1.pic_stride1 *
			rxCfg->sc_image_info.sc_height >> 1;
		break;
	case YUV4:
		plane_size[0] = rxCfg->axi_fmt_stride0.pic_stride0 *
			rxCfg->sc_image_info.sc_height;
		plane_size[1] = rxCfg->axi_fmt_stride1.pic_stride1 *
			rxCfg->sc_image_info.sc_height;
		break;
	}
	bt_debug(2,
		"bank_addr configure: plane0_size=0x%08x plane1_size=0x%08x\n",
		plane_size[0], plane_size[1]);

	for (i = 0; i < rxCfg->bank_num; i++) {
		//continuous
		rxCfg->bank_addr[i][0] =
			(uint32_t *)(((uintptr_t)addr_base +
			i * rxCfg->dst_img_size + 0x0F) & 0xFFFFFFF0);
		WriteReg32(&rx->bank_addr[i][0],
			(uintptr_t)rxCfg->bank_addr[i][0]);

		rxCfg->bank_addr[i][1] =
			(uint32_t *)(((uintptr_t)addr_base + plane_size[0] +
			i * rxCfg->dst_img_size + 0x0F) & 0xFFFFFFF0);
		WriteReg32(&rx->bank_addr[i][1],
			(uintptr_t)rxCfg->bank_addr[i][1]);

		rxCfg->bank_addr[i][2] =
			(uint32_t *)(((uintptr_t)addr_base + plane_size[0] +
			plane_size[1] + i * rxCfg->dst_img_size + 0x0F) &
			0xFFFFFFF0);
		WriteReg32(&rx->bank_addr[i][2],
			(uintptr_t)rxCfg->bank_addr[i][2]);

		bt_debug(2, "%p: 0x%08lx\n%p: 0x%08lx\n%p: 0x%08lx: bank addr %d.\n",
			&rx->bank_addr[i][0], (uintptr_t)rxCfg->bank_addr[i][0],
			&rx->bank_addr[i][1], (uintptr_t)rxCfg->bank_addr[i][1],
			&rx->bank_addr[i][2], (uintptr_t)rxCfg->bank_addr[i][2],
			i);

		//continuous
		rxCfg->bank_vaddr[i][0] =
			(void *)(((uintptr_t)rxCfg->dma_vaddr +
			i * rxCfg->dst_img_size + 0x0F) & 0xFFFFFFF0);

		rxCfg->bank_vaddr[i][1] =
			(void *)(((uintptr_t)rxCfg->dma_vaddr + plane_size[0] +
			i * rxCfg->dst_img_size + 0x0F) & 0xFFFFFFF0);

		rxCfg->bank_vaddr[i][2] =
			(void *)(((uintptr_t)rxCfg->dma_vaddr + plane_size[0] +
			plane_size[1] + i * rxCfg->dst_img_size + 0x0F)
			& 0xFFFFFFF0);
	}

	WriteReg32(&rx->frame_sample_period, rxCfg->frame_sample_perid);
	bt_debug(2, "%p: 0x%08x : frame_sameple_period.\n",
		&rx->frame_sample_period, rxCfg->frame_sample_perid);
	WriteReg32(&rx->bank_number, rxCfg->bank_num);
	bt_debug(2, "%p: 0x%08x : bank_num.\n",
		&rx->bank_number, rxCfg->bank_num);
}

void bt1120rx_interupt_enable(bool enable)
{
	uint32_t int_en = 0;

	if (enable)
		SETBIT(int_en, INTERUPT_ENABLE);

	WriteReg32(&rx->interupt_enable, int_en);
	bt_debug(2, "%p: 0x%08x : interrupt %sable.\r\n",
	 &rx->interupt_enable, int_en, enable ? "en" : "dis");
}

uint32_t bt1120rx_GetIntrStatus(void)
{
	uint32_t status = ReadReg32(&rx->interupt_status);

	bt_debug(2, "interrupt status = 0x%08x\r\n", status);
	return status;
}

uint32_t bt1120rx_GetIntrRawStatus(void)
{
	uint32_t status = ReadReg32(&rx->interupt_raw_status);

	bt_debug(2, "interrupt RAW status = 0x%08x\r\n", status);
	return status;
}

void bt1120_rx_irqhandler(int32_t idx)
{
	uint32_t status = bt1120rx_GetIntrStatus();

	bt_debug(2, "************ interrupt RX * 0x%08x\r\n", status);

	/* prase one interrupt in one time ? */
	if (status & INT_BANK0) {
		bt_debug(2, "interrupt: bank0_done\n");
		bt1120rx_ClrIntr(INT_BANK0);
	}
	if (status & INT_BANK1) {
		bt_debug(2, "interrupt: bank1_done\n");
		bt1120rx_ClrIntr(INT_BANK1);
	}
	if (status & INT_BANK2) {
		bt_debug(2, "interrupt: bank2_done\n");
		bt1120rx_ClrIntr(INT_BANK2);
	}
	if (status & INT_BANK3) {
		bt_debug(2, "interrupt: bank3_done\n");
		bt1120rx_ClrIntr(INT_BANK3);
	}
	if (status & INT_BANK4) {
		bt_debug(2, "interrupt: bank4_done\n");
		bt1120rx_ClrIntr(INT_BANK4);
	}
	if (status & INT_BANK5) {
		bt_debug(2, "interrupt: bank5_done\n");
		bt1120rx_ClrIntr(INT_BANK5);
	}
}

uint32_t bt1120rx_GetRxStatus(void)
{
	bt1120_status status;
	uint32_t status_val = ReadReg32(&rx->bt1120_status);

	status.bt1120_video_lost = status_val & 0x01;
	if (status.bt1120_video_lost)
		bt_debug(2, "Status: video loss !!!\n");

	status.bt1120_error_flg = (status_val >> 8) & 0x0F;
	switch (status.bt1120_error_flg) {
	case 0:
		break;
	case 1:
		bt_debug(2, "Status: Can't Detect Time Reference\n");
		break;
	case 2:
		bt_debug(2, "Status: YUV Time Reference mismatching\n");
		break;
	case 3:
		bt_debug(2, "Status: Width Configure Fault\n");
		break;
	case 4:
		bt_debug(2, "Status: Height Configure Fault\n");
		break;
	default:
		bt_debug(2, "Status: %d\n", status_val);
		break;
	}

	return status_val;
}

s32 bt1120rx_ClrIntr(uint32_t intrStatus)
{
	if (intrStatus & INT_BANK0)
		WriteReg32(&rx->interupt_clear, INT_BANK0);

	if (intrStatus & INT_BANK1)
		WriteReg32(&rx->interupt_clear, INT_BANK1);

	if (intrStatus & INT_BANK2)
		WriteReg32(&rx->interupt_clear, INT_BANK2);

	if (intrStatus & INT_BANK3)
		WriteReg32(&rx->interupt_clear, INT_BANK3);

	if (intrStatus & INT_BANK4)
		WriteReg32(&rx->interupt_clear, INT_BANK4);

	if (intrStatus & INT_BANK5)
		WriteReg32(&rx->interupt_clear, INT_BANK5);


	return 0;
}

void bt1120rx_SoftRestDVP(bt1120_ctrl *dvpCtrl, bt1120_Rx_Regs *rx)
{
	uint32_t bt1120_ctrl_val = 0x0e;// = ReadReg32(&rx->bt1120_ctrl);

	bt1120_ctrl_val |= dvpCtrl->dvp_sft_rst << 31;
	WriteReg32(&rx->bt1120_ctrl, bt1120_ctrl_val);

	mdelay(500);
}

void bt1120rx_config_decCtrl(bt1120_ctrl *dvpCtrl, bt1120_Rx_Regs *rx)
{
	uint32_t bt1120_ctrl_val;

	if (dvpCtrl->dvp_sft_rst)
		bt1120rx_SoftRestDVP(dvpCtrl, rx);

	bt1120_ctrl_val =
		(dvpCtrl->bt1120_dec_mode << bt1120_DEC_MODE) |
		(dvpCtrl->bt1120_check_en << bt1120_CHECK_EN) |
		(dvpCtrl->bt1120_range_en << bt1120_RANGE_EN) |
		(dvpCtrl->bt1120_data_mode << bt1120_DATA_MODE);

	RESETBIT(bt1120_ctrl_val, bt1120_DEC_EN); //first disable

	WriteReg32(&rx->bt1120_ctrl, bt1120_ctrl_val);
	bt_debug(2, "%p: 0x%08x : configure dec ctrl.\r\n",
		&rx->bt1120_ctrl, bt1120_ctrl_val);
}

void bt1120rx_enable(void)
{
	uint32_t bt1120_ctrl_val = ReadReg32(&rx->bt1120_ctrl);

	SETBIT(bt1120_ctrl_val, bt1120_DEC_EN); //enable
	WriteReg32(&rx->bt1120_ctrl, bt1120_ctrl_val);
	bt_debug(2, "%p: 0x%08x : DEC enable.\r\n",
		&rx->bt1120_ctrl, bt1120_ctrl_val);

	mdelay(500);
}

void bt1120rx_disable(void)
{
	uint32_t bt1120_ctrl_val = ReadReg32(&rx->bt1120_ctrl);

	bt1120_ctrl_val &= 0xfffffffe;
	WriteReg32(&rx->bt1120_ctrl, bt1120_ctrl_val);

	mdelay(500);
}

void bt1120rx_config_axi_stride(bt1120rx_Config *rxCfg)
{
	uint32_t axi_format_stride0_val;

	switch (rxCfg->pic_mode) {
	case ORGB://0
		rxCfg->axi_fmt_stride0.pic_stride0 =
			(uint32_t)(rxCfg->sc_image_info.sc_width *
			rxCfg->dst_pix_bits) / 8;
		break;
	case RGB_DIV://0 1 2
		rxCfg->axi_fmt_stride0.pic_stride0 =
			rxCfg->sc_image_info.sc_width;
		rxCfg->axi_fmt_stride1.pic_stride1 =
			rxCfg->sc_image_info.sc_width;
		rxCfg->axi_fmt_stride1.pic_stride2 =
			rxCfg->sc_image_info.sc_width;
		WriteReg32(&rx->axi_format_stride1,
			rxCfg->axi_fmt_stride1.pic_stride1 |
			rxCfg->axi_fmt_stride1.pic_stride2 << 16);
		break;
	case UYVY://0
		rxCfg->axi_fmt_stride0.pic_stride0 =
			(uint32_t)(rxCfg->sc_image_info.sc_width *
			rxCfg->dst_pix_bits) / 8;
		break;
	case YUYV://0
		rxCfg->axi_fmt_stride0.pic_stride0 =
			(uint32_t)(rxCfg->sc_image_info.sc_width *
			rxCfg->dst_pix_bits) / 8;
		break;
	case IYUV://0 1 2 PLANNER
		rxCfg->axi_fmt_stride0.pic_stride0 =
			rxCfg->sc_image_info.sc_width;
		rxCfg->axi_fmt_stride1.pic_stride1 =
			rxCfg->axi_fmt_stride0.pic_stride0 >> 1; //continuous
		rxCfg->axi_fmt_stride1.pic_stride2 =
			rxCfg->axi_fmt_stride1.pic_stride1;	//continuous
		WriteReg32(&rx->axi_format_stride1,
			rxCfg->axi_fmt_stride1.pic_stride1 |
			rxCfg->axi_fmt_stride1.pic_stride2 << 16);
		break;
	case YUV4://0 1 2
		rxCfg->axi_fmt_stride0.pic_stride0 =
			rxCfg->sc_image_info.sc_width;

		rxCfg->axi_fmt_stride1.pic_stride1 =
			rxCfg->sc_image_info.sc_width;

		rxCfg->axi_fmt_stride1.pic_stride2 =
			rxCfg->sc_image_info.sc_width;

		WriteReg32(&rx->axi_format_stride1,
			rxCfg->axi_fmt_stride1.pic_stride1 |
			rxCfg->axi_fmt_stride1.pic_stride2 << 16);
		break;
	case U8:
		rxCfg->axi_fmt_stride0.pic_stride0 =
			rxCfg->sc_image_info.sc_width;
		break;
	}
	axi_format_stride0_val =
		rxCfg->axi_fmt_stride0.pic_stride_en |
		rxCfg->axi_fmt_stride0.pic_stride0 << 16;
	WriteReg32(&rx->axi_format_stride0, axi_format_stride0_val);

	bt_debug(2, "%p: 0x%08x : configure axi_format_stride.\r\n",
		&rx->axi_format_stride0, axi_format_stride0_val);
}

void bt1120rx_status_info(bt1120rx_Config *rxCfg)
{
	bt1120rx_video_output_info(rxCfg, rx);
	bt1120rx_ready_info(rxCfg, rx);
	bt1120rx_test_status(rxCfg, rx);
	bt1120rx_dump_y_info(rxCfg, rx);
}

int bt1120rx_hw_init(bt1120rx_Config *rxCfg)
{
#if 0
	static uint32_t base, irq, ret;
	static void *handler;

	ret = target_bt1120_init(0, &base, &irq, &handler);
	if (ret < 0 || ret >= CONFIG_bt1120_NUM)
		return ERROR;

	static struct IrqTableEntry Entry;

	Entry.Handler = handler;
	Entry.data = NULL;
	drv_irq_register(irq, &Entry);
	drv_irq_enable(irq);
#endif

	//spin_lock(&bt_rx->irq_lock);
	bt1120rx_disable();
	bt1120rx_config_decCtrl(&rxCfg->bt1120_ctrl, rx);
	bt1120rx_video_input_config(rxCfg);
	bt1120rx_interupt_enable(true);
	bt1120rx_ConfigScaling(rxCfg, rx);
	bt1120rx_ConfigGsg(rxCfg);
	bt1120rx_config_axi_stride(rxCfg);
	bt1120rx_config_output_video(rxCfg);
	bt1120rx_config_bank_addr(rxCfg);
	bt1120rx_info_extr_enable(rxCfg);

	bt1120rx_enable();

	//spin_unlock(&bt_rx->irq_lock);

	return 0;
}

/* don't use */
void IOCTRL_ConfigDVPRx(void)
{
	uint32_t BT_OEN = 0x80;

	WriteReg32((unsigned int *)(IOCTRL_BASE_ADDR + 0xC0), BT_OEN);
}

struct ts_bt1120rx {
	bt1120rx_Config rxCfg;
	void __iomem *reg_base;
	struct clk *clk;
	uint64_t clk_rate; /* bus interface clock rate */
	struct device *dev;

	struct miscdevice	  misc_dev;

	/* elements used by ISR */
	struct completion complete;
	spinlock_t irq_lock;
	uint32_t irq_mask;
	uint32_t irq_status;
	uint32_t irq;

	int minor;
	int group;
	struct sys_frame_mgr *frm_mgr;

	unsigned long grp_mask;
	struct mutex grp_lock;
};

struct ts_bt1120rx_device_data {
	unsigned int revision;
};

static const struct ts_bt1120rx_device_data ts_bt1120rx_data = {
	.revision = 100,
};

void init_mem(void)
{
#if 0
	bank_addr0 = malloc(dst_width * dst_height * dst_pixbit);
	// 16 byte align ?
	bank_addr1 = malloc(dst_width * dst_height * dst_pixbit);
	if ((bank_addr0 == NULL) || (bank_addr1 == NULL))
		qw_printf("malloc failure\n");

	qw_printf("bank_addr0 addr: %p\n bank_addr1 addr: %p\n",
			bank_addr0, bank_addr1);
#endif
//---------------------------Mem INITIALIZE--------------------------//
#if 0
	for (i = 0; i < dst_height; i++) {
		for (j = 0; j < dst_width; j++) {
			bank_addr0[i * dst_width * 4 + j * 4 + 0] = 0x00;
			bank_addr0[i * dst_width * 4 + j * 4 + 1] = 0xff;
			bank_addr0[i * dst_width * 4 + j * 4 + 2] = 0x00;
			bank_addr0[i * dst_width * 4 + j * 4 + 3] = 0xff;

			bank_addr1[i * dst_width * 4 + j * 4 + 0] = 0x00;
			bank_addr1[i * dst_width * 4 + j * 4 + 1] = 0xff;
			bank_addr1[i * dst_width * 4 + j * 4 + 2] = 0x00;
			bank_addr1[i * dst_width * 4 + j * 4 + 3] = 0xff;
		}
	}
#endif
//------------------------------------------------------------------//
}


void bt1120rx_pre_config(struct ts_bt1120rx *bt_rx)
{
	bt1120rx_Config *rxCfg = &bt_rx->rxCfg;

	//user configure
	rxCfg->frame_sample_perid =
		EVERY_FRAME;//TWO_FRAME;//FOUR_FRAME;//save one frame
	rxCfg->bank_num = BANK_NUMBER_2;	//two bank numbers

	//rxCfg->pic_mode = ORGB;	// orgb 4 byte
	//rxCfg->pic_mode = RGB_DIV;
	//rxCfg->pic_mode = UYVY;
	//rxCfg->pic_mode = YUYV;
	rxCfg->pic_mode = IYUV;		//ok
	//rxCfg->pic_mode = YUV4;
	//rxCfg->pic_mode = U8;

#if 0
	rxCfg->src_width = 1280;//1920;
	rxCfg->src_height = 720;//1080;
	rxCfg->dst_width = 1280;//800;
	rxCfg->dst_height = 720;//400;
	//rxCfg->dst_width = 640;//800;
	//rxCfg->dst_height = 480;//400;
	//rxCfg->dst_width = 320;//800;
	//rxCfg->dst_height = 240;//400;
#else
	rxCfg->src_width = 1920;//1280;//1920;
	rxCfg->src_height = 1080;//720;//1080;
	rxCfg->dst_width = 640;//1280;//800;
	rxCfg->dst_height = 480;//720;//400;
#endif

	rxCfg->bt1120_ctrl.bt1120_dec_mode =
		AUTO_DEC_MODE;	// auto detect dec
    //rxCfg->bt1120_ctrl.bt1120_dec_mode = MANUAL_DEC_MODE;
    //rxCfg->bt1120_ctrl.bt1120_check_en = DVP_CHECK_DIS;
	rxCfg->bt1120_ctrl.bt1120_check_en = DVP_CHECK_EN;
	rxCfg->bt1120_ctrl.bt1120_range_en =
		DVP_RANGE_DIS;//DVP_RANGE_EN;	// limit range
	rxCfg->bt1120_ctrl.bt1120_data_mode =
		DVP_DATA_MODE0; // 0: Y high 8 bit 1: UV high 8 bit
	rxCfg->bt1120_ctrl.dvp_sft_rst =
		DVP_SFT_RST_EN;//DVP_SFT_RST_DIS;	// disable soft reset

	rxCfg->axi_fmt_stride0.pic_stride_en =
		AXI_PIC_STRIDE_DIS; /*AXI_PIC_STRIDE_EN;//*/
	//rxCfg->axi_fmt_stride0.pic_stride_en = AXI_PIC_STRIDE_EN;
	rxCfg->frame_info_extr_en = FALSE;//TRUE;

	switch (rxCfg->pic_mode) {
	case ORGB:
		rxCfg->dst_pix_bits = 32;	break;
	case RGB_DIV:
		rxCfg->dst_pix_bits = 24;	break;
	case UYVY:
		rxCfg->dst_pix_bits = 16;	break;
	case YUYV:
		rxCfg->dst_pix_bits = 16;	break;
	case IYUV:
		rxCfg->dst_pix_bits = 12;	break;
	case YUV4:
		rxCfg->dst_pix_bits = 24;	break;
	case U8:
		rxCfg->dst_pix_bits = 8;		break;
	}

	//rxCfg->frame_freq = FREQ_30P;
    //rxCfg->output_info1.bt1120_frame_freq = rxCfg->frame_freq;

	rxCfg->src_img_size = (rxCfg->src_width * rxCfg->src_height * 3) >> 2;
	rxCfg->dst_img_size = rxCfg->dst_width *
		rxCfg->dst_height * rxCfg->dst_pix_bits / 8;

}

int bt1120rx_ioctl(struct platform_device *pdev)
{
	struct ts_bt1120rx *bt_rx = platform_get_drvdata(pdev);
	bt1120rx_Config rxCfg = bt_rx->rxCfg;
	//bt_debug(2, "bt1120 system begin Runing\n");
	//IOCTL_ConfigDVPRx(); // ???
	//dpu_test_init();

	//case 1:
	//reinit_completion(&bt_rx->complete);
	bt1120rx_pre_config(bt_rx);
	bt1120rx_hw_init(&rxCfg);
	bt_debug(2, "bt1120rx Config Finish\n");

	//case 2:
	bt1120rx_status_info(&rxCfg);
	bt1120rx_GetRxStatus();
    //bt1120rx_GetIntrStatus();
    //bt1120_rx_irqhandler(0);
	bt1120rx_GetIntrRawStatus();
    //debug_print();	// debug massage.

	return 0;
}

static irqreturn_t ts_isr(int irq, void *dev_id)
{

	struct ts_bt1120rx *bt_rx = dev_id;
	irqreturn_t ret = IRQ_NONE;
	uint32_t status;
	unsigned long flags;
	//uint32_t irq_status;
	//int i;

	//spin_lock(&bt_rx->irq_lock);
	spin_lock_irqsave(&bt_rx->irq_lock, flags);
	//TODO...
	//status = bt1120rx_GetIntrStatus();
	status = bt1120rx_GetIntrRawStatus();

	bt_debug(2, "*** interrupt BT_RX * 0x%08x\r\n", status);

	/* prase one interrupt in one time ? */
	if (status & INT_BANK0) {
		bt_rx->rxCfg.frame_index++;
		bt_debug(2, "interrupt: bank0_done\n");
	}
	if (status & INT_BANK1) {
		bt_rx->rxCfg.frame_index++;
		bt_debug(2, "interrupt: bank1_done\n");
	}
	if (status & INT_BANK2) {
		bt_rx->rxCfg.frame_index++;
		bt_debug(2, "interrupt: bank2_done\n");
	}
	if (status & INT_BANK3) {
		bt_rx->rxCfg.frame_index++;
		bt_debug(2, "interrupt: bank3_done\n");
	}
	if (status & INT_BANK4) {
		bt_rx->rxCfg.frame_index++;
		bt_debug(2, "interrupt: bank4_done\n");
	}
	if (status & INT_BANK5) {
		bt_rx->rxCfg.frame_index++;
		bt_debug(2, "interrupt: bank5_done\n");
	}
	//complete(&bt_rx->complete);
	bt1120rx_ClrIntr(status);
	bt_rx->rxCfg.interupt_raw_status = status;

	//debug...
	bt1120rx_status_info(&bt_rx->rxCfg);
	bt1120rx_GetRxStatus();
	bt1120rx_GetIntrStatus();

	//complete(&bt_rx->complete);
	//mmio_write_32((uintptr_t)&nfc_regs->int_status, 0);

	//spin_unlock(&bt_rx->irq_lock);
	spin_unlock_irqrestore(&bt_rx->irq_lock, flags);

	ret = IRQ_HANDLED;
	return ret;
}

static int ts_bt1120rx_parse_dt(struct platform_device *pdev,
		struct ts_bt1120rx *bt_rx)
{
	struct resource *res;
	struct device *dev = &pdev->dev;
	//struct device_node *np = dev->of_node;
	struct reset_control *rstc;
	int ret;

	bt_rx->dev = &pdev->dev;

	//res
	//res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ts-bt1120rx");
	if (!res) {
		dev_err(&pdev->dev, "missing IO resource\n");
		return -ENODEV;
	}
	bt_rx->reg_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(bt_rx->reg_base))
		return PTR_ERR(bt_rx->reg_base);
	rx = (struct _bt1120_Rx_Regs *)bt_rx->reg_base;
	dev_dbg(&pdev->dev, "res->start:0x%08x\n", (uint32_t)res->start);

	//clk init todo...
	bt_rx->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(bt_rx->clk)) {
		dev_err(&pdev->dev, "Cannot claim bt1120RX clock.\n");
		ret = PTR_ERR(bt_rx->clk);
		goto io_unmap;
	}
	ret = clk_prepare_enable(bt_rx->clk);
	if (ret) {
		dev_err(&pdev->dev, "Cannot enable bt1120RX clock.\n");
		goto io_unmap;
	}
	bt_rx->clk_rate = clk_get_rate(bt_rx->clk);
	dev_info(&pdev->dev, "clock rate %lld\n", bt_rx->clk_rate);

	/* Obtain bt1120RX reset control */
	rstc = devm_reset_control_get_optional_exclusive(dev,
		"bt1120rx_global");
	if (IS_ERR(rstc)) {
		ret = PTR_ERR(rstc);
		dev_err(dev, "Cannot get bt1120RX reset.\n");
		goto out_disable_clk;
	}
	reset_control_assert(rstc);
	udelay(5);
	reset_control_deassert(rstc);

	//irq
	//bt_rx->irq = platform_get_irq_byname(pdev, TS_bt1120RX_NAME);
	bt_rx->irq = platform_get_irq(pdev, 0);
	if (bt_rx->irq < 0) {
		dev_err(&pdev->dev, "no irq defined\n");
		ret = bt_rx->irq;
		goto reset_failed;
	}
	dev_dbg(&pdev->dev, " irq is %d\n", bt_rx->irq);

	/* Request IRQ after all the harware initalization is finished */
	ret = devm_request_irq(bt_rx->dev, bt_rx->irq,
		ts_isr, IRQF_SHARED, TS_bt1120RX_NAME, bt_rx);
	if (ret) {
		dev_err(&pdev->dev, "Unable to request IRQ %d.\n", bt_rx->irq);
		goto reset_failed;
	}

	//init
	ret = bt1120rx_hw_init(&bt_rx->rxCfg);
	if (ret)
		goto free_irq;

	return 0;

free_irq:
	devm_free_irq(&pdev->dev, bt_rx->irq, bt_rx);
reset_failed:
out_disable_clk:
	clk_disable_unprepare(bt_rx->clk);
io_unmap:
	devm_iounmap(&pdev->dev, bt_rx->reg_base);
	return ret;
}

/* initialize driver data structures */
static void ts_drv_init(struct ts_bt1120rx *bt_rx)
{
	/*
	 * the completion object will be used to notify
	 * the callee that the interrupt is done
	 */
	//init_completion(&bt_rx->complete);

	/*
	 * the spinlock will be used to synchronize the ISR with any
	 * element that might be access shared data (interrupt status)
	 */
	spin_lock_init(&bt_rx->irq_lock);
}

static int ts_bt1120rx_open(struct inode *inode, struct file *file)
{
	struct ts_bt1120rx *bt_rx = NULL;
	int ret = 0;

	//bt_rx = container_of(inode->i_cdev, struct ts_bt1120rx, misc_dev);
	if (g_bt_rx) {
		bt_rx = g_bt_rx;
	} else {
		bt_rx = kzalloc(sizeof(*bt_rx), GFP_KERNEL);
		if (!bt_rx) {
			//pr_err("bt1120rx open kzalloc is fail\n");
			ret = -ENOMEM;
			goto p_err;
		}
	}

	file->private_data = bt_rx;

	return 0;

p_err:
	return ret;
}

static int ts_bt1120rx_release(struct inode *inode, struct file *filp)
{
	if (g_bt_rx == NULL)
		kfree(filp->private_data);

	return 0;
}

static ssize_t ts_bt1120rx_read(struct file *file,
		char __user *buff, size_t count, loff_t *offp)
{
	return 0;
}

static ssize_t ts_bt1120rx_write(struct file *file,
		const char *buff, size_t count, loff_t *offp)
{
	return 0;
}

static int bt1120rx_bind_group(struct ts_bt1120rx *bt_rx, unsigned long arg)
{

	return 0;
}

static int bt1120rx_init(struct ts_bt1120rx *bt_rx, unsigned long arg)
{
	return 0;
}

#if 0
static int bt1120rx_req_buf(struct ts_bt1120rx *bt_rx, unsigned long arg)
{
	return 0;
}
#endif

static int bt1120rx_stream(struct ts_bt1120rx *bt_rx, unsigned long arg)
{
	return 0;
}

static int bt1120rx_qbuf(struct ts_bt1120rx *bt_rx, unsigned long arg)
{
	//unsigned long flag;
	//struct sys_frame_mgr *fmgr;
	//struct sys_frame *frame;
	int ret;
	struct bt1120rx_frame_info frm_info;

	ret = copy_from_user((char *)&frm_info, (int __user *)arg,
		sizeof(struct bt1120rx_frame_info));
	if (ret) {
		ret = -1; goto err;
	}

	if ((frm_info.w == 0) || (frm_info.w > 0xFFFF)
		|| (frm_info.h == 0) || (frm_info.h > 0xFFFF)
		|| (frm_info.stride[0] > 0xFFFF)
		|| (frm_info.stride[1] > 0xFFFF)
		|| (frm_info.stride[2] > 0xFFFF)) {
		pr_err("[G%d][D%d]%s input err:wh(%d %d), off(%d %d %d)\n",
			bt_rx->group, bt_rx->minor, __func__,
			frm_info.w, frm_info.h, frm_info.stride[0],
			frm_info.stride[1], frm_info.stride[2]);
		ret = -2; goto err;
	}

	if (!frm_info.stride[0]) {
		frm_info.stride[0] = frm_info.w;
		frm_info.stride[1] = frm_info.w;
	}
	//todo...

	return 0;

err:
	return ret;
}

static int bt1120rx_dqbuf(struct ts_bt1120rx *bt_rx, unsigned long arg)
{
	return 0;
}


static long ts_bt1120rx_ioctl(struct file *file,
		unsigned int cmd, unsigned long arg)
{
	int ret = 0;
	struct ts_bt1120rx *bt_rx;
	int reset;
	//int group;

	bt_rx = file->private_data;
	if (unlikely(bt_rx == NULL)) {
		pr_err("file bt_rx error.\n");
		return -EFAULT;
	}

	if (_IOC_TYPE(cmd) != BT1120RX_IOC_MAGIC)
		return -EFAULT;

	switch (cmd) {
	case BT1120RX_IOC_BIND_GROUP:
		ret = bt1120rx_bind_group(bt_rx, arg);
		if (ret)
			return ret;
		break;
	case BT1120RX_IOC_INIT:
		ret = bt1120rx_init(bt_rx, arg);
		if (ret)
			return -EFAULT;
		break;
	case BT1120RX_IOC_QBUF:
		ret = bt1120rx_qbuf(bt_rx, arg);
		if (ret)
			return ret;
		break;
	case BT1120RX_IOC_STREAM:
		ret = bt1120rx_stream(bt_rx, arg);
		if (ret)
			return ret;
		break;
	case BT1120RX_IOC_DQBUF:
		ret = bt1120rx_dqbuf(bt_rx, arg);
		if (ret)
			return ret;
		break;
	case BT1120RX_IOC_STATUS:
		break;
	case BT1120RX_IOC_GET_CFG:
		break;
	case BT1120RX_IOC_REST_HW:
		ret = get_user(reset, (int __user *)arg);
		if (unlikely(ret)) {
			pr_err("get reset data err.\n");
			return -EFAULT;
		}
		if (reset)
			bt1120rx_SoftRestDVP(&bt_rx->rxCfg.bt1120_ctrl,
				bt_rx->reg_base);

		break;
	default:
		pr_err("%s unknow ioctl cmd %x\n", __func__, cmd);
		ret = -EFAULT;
		break;
	}

	return 0;
}

static const struct file_operations bt1120rx_drv_fops = {
	.owner = THIS_MODULE,
	.open = ts_bt1120rx_open,
	.read = ts_bt1120rx_read,
	.write = ts_bt1120rx_write,
	.release = ts_bt1120rx_release,
	.unlocked_ioctl = ts_bt1120rx_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = ts_bt1120rx_ioctl,
#endif
};


static int ts_bt1120rx_probe(struct platform_device *pdev)
{
	int ret;
	struct ts_bt1120rx *bt_rx; //driver data
	int using_dac, consistent_using_dac;

	dev_dbg(&pdev->dev, "bt1120rx_probe\n");
	bt_rx = devm_kzalloc(&pdev->dev, sizeof(*bt_rx), GFP_KERNEL);
	if (!bt_rx)
		return -ENOMEM;

	g_bt_rx = bt_rx;
	ts_drv_init(bt_rx);

	bt1120rx_pre_config(bt_rx);
	ret = of_reserved_mem_device_init(&pdev->dev);
	if (ret)
		dev_info(&pdev->dev, "init reserved memory failed\n");
		/* continue to use dynamic allocation if failed */

	if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
		using_dac = 1;
		consistent_using_dac = 1;
	} else if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
		using_dac = 0;
		consistent_using_dac = 0;
	} else {
		dev_warn(&pdev->dev, "No suitable DMA available\n");
		//goto ignore_this_device;
	}

	bt_rx->rxCfg.dma_size = bt_rx->rxCfg.bank_num * 1920 * 1080 * 4;
	if (bt_rx->rxCfg.dma_size > SZ_32M)
		bt_rx->rxCfg.dma_size = SZ_32M;

	bt_rx->rxCfg.dma_vaddr = dma_alloc_coherent(&pdev->dev,
			 bt_rx->rxCfg.dma_size,
			  &bt_rx->rxCfg.dma_handler, GFP_KERNEL);
	dev_dbg(&pdev->dev, "dma alloc 0x%llx to %p!\n",
		bt_rx->rxCfg.dma_handler, bt_rx->rxCfg.dma_vaddr);

	/* we allocate the misc device structure as part of our own allocation,
	 * so we can get a pointer to our priv structure later on with
	 * container_of(). This isn't really necessary as we have a fixed minor
	 * number anyway, but this is to avoid statics.
	 */
#if defined(TS_BT1120RX_MINOR)
	bt_rx->misc_dev.minor	= TS_BT1120RX_MINOR,
#else
	bt_rx->misc_dev.minor	= TS_bt1120RX_MISCDEV_MINOR,
#endif
	bt_rx->misc_dev.name	= TS_bt1120RX_NAME,
	bt_rx->misc_dev.fops	= &bt1120rx_drv_fops;

	/* register misc device */
	ret = misc_register(&bt_rx->misc_dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "misc_register() for minor %d failed\n",
			TS_bt1120RX_MISCDEV_MINOR);
		goto err_misc_deregister;
	}

	ret = ts_bt1120rx_parse_dt(pdev, bt_rx);
	if (ret)
		goto free_dma;

	//complete(&bt_rx->complete);

	platform_set_drvdata(pdev, bt_rx);

	dev_info(&pdev->dev, "ts bt1120rx initialized.\n");

	bt1120rx_status_info(&bt_rx->rxCfg);
	bt1120rx_GetRxStatus();
    //bt1120rx_GetIntrStatus();
    //bt1120_rx_irqhandler(0);
	bt1120rx_GetIntrRawStatus();
	//wait_for_completion_timeout(&bt_rx->complete, msecs_to_jiffies(200));

	return 0;

err_misc_deregister:
	misc_deregister(&bt_rx->misc_dev);
free_dma:
	dma_free_coherent(&pdev->dev, bt_rx->rxCfg.dma_size,
		 bt_rx->rxCfg.dma_vaddr, bt_rx->rxCfg.dma_handler);
	devm_kfree(&pdev->dev, bt_rx);

	return ret;

}

static void ts_bt1120rx_interrupts_disable(struct ts_bt1120rx *bt_rx)
{
	unsigned long flags;

	spin_lock_irqsave(&bt_rx->irq_lock, flags);
	bt_rx->irq_mask = 0;
	bt1120rx_interupt_enable(bt_rx->irq_mask);
	spin_unlock_irqrestore(&bt_rx->irq_lock, flags);
}

static int ts_bt1120rx_remove(struct platform_device *pdev)
{
	struct ts_bt1120rx *bt_rx = platform_get_drvdata(pdev);

	/* shutdown irq */
	ts_bt1120rx_interrupts_disable(bt_rx);

	misc_deregister(&bt_rx->misc_dev);
	clk_disable_unprepare(bt_rx->clk);
	devm_free_irq(&pdev->dev, bt_rx->irq, bt_rx);
	dma_free_coherent(&pdev->dev, bt_rx->rxCfg.dma_size,
		 bt_rx->rxCfg.dma_vaddr, bt_rx->rxCfg.dma_handler);

	devm_iounmap(&pdev->dev, bt_rx->reg_base);
	devm_kfree(&pdev->dev, bt_rx);

	return 0;
}

static int ts_bt1120rx_suspend(struct platform_device *pdev, pm_message_t state)
{
	return 0;
}

static int ts_bt1120rx_resume(struct platform_device *pdev)
{
	return 0;
}

static void ts_bt1120rx_shutdown(struct platform_device *pdev)
{
}

#if defined(CONFIG_OF) || 1
static const struct of_device_id ts_bt1120rx_of_match[] = {
	{.compatible = "ts,bt1120rx",
	 .data = &ts_bt1120rx_data,
	},

	{}
};
MODULE_DEVICE_TABLE(of, ts_bt1120rx_of_match);
#endif

static struct platform_driver ts_bt1120rx_driver = {
	.driver = {
		.name = "ts-bt1120rx",
		.of_match_table = of_match_ptr(ts_bt1120rx_of_match),
	},
	.probe = ts_bt1120rx_probe,
	.remove = ts_bt1120rx_remove,
	.suspend = ts_bt1120rx_suspend,
	.resume = ts_bt1120rx_resume,
	.shutdown = ts_bt1120rx_shutdown,
};

#if 0
static int __init ts_bt1120rx_init(void)
{
	return platform_dirver_register(&ts_bt1120rx_driver);
}

//arch_initcall(ts_bt1120rx_init);

static int __exit ts_bt1120rx_exit(void)
{
	return platform_driver_unregister(&ts_bt1120rx_driver);
}
#endif
/* register platform driver to platform bus */
module_platform_driver(ts_bt1120rx_driver);

MODULE_DESCRIPTION("TS bt1120RX driver");
MODULE_AUTHOR("Json Liu, <liuluyang530@126.com>");
MODULE_LICENSE("GPL");

tx部分:

/***************************************************************************
 * Copyright (C) 2021,All rights reserved.
 * Version     : V1.0
 * Description : support YUV420 and RGB888
 ***************************************************************************/

#ifndef _TS_BT1120TX_H_
#define _TS_BT1120TX_H_
#include <uapi/linux/types.h>
#include <linux/ioctl.h>

#ifdef __KERNEL__
#include <linux/time.h>
#else
#include <sys/time.h>
#endif

#ifdef __cplusplus
extern "C" {  /* C declaration in C++ */
#endif /* _cplusplus */

#define TS_BT1120TX_NAME "bt1120tx"
#define TS_BT1120TX_MISCDEV_MINOR 244

/* command for ioctl() */
#define BT1120TX_IOC_MAGIC 't'
#define BT1120TX_IOC_BIND_GROUP		_IOW(BT1120TX_IOC_MAGIC, 0, int)

#define BT1120TX_IOC_INIT			_IOW(BT1120TX_IOC_MAGIC, 1, int)
#define BT1120TX_IOC_REQBUFS		_IOW(BT1120TX_IOC_MAGIC, 2, int)
#define BT1120TX_IOC_STREAM			_IOW(BT1120TX_IOC_MAGIC, 3, int)
#define BT1120TX_IOC_QBUF			_IOW(BT1120TX_IOC_MAGIC, 4, int)
#define BT1120TX_IOC_DQBUF			_IOW(BT1120TX_IOC_MAGIC, 5, int)
#define BT1120TX_IOC_STATUS			_IOW(BT1120TX_IOC_MAGIC, 6, int)
#define BT1120TX_IOC_GET_CFG		_IOW(BT1120TX_IOC_MAGIC, 7, int)
#define BT1120TX_IOC_REST_HW		_IOW(BT1120TX_IOC_MAGIC, 8, int)

#define BT1120TX_FRME_MAX_PLANES	3

/* used in q/dq ioctl */
struct bt1120tx_frame_info {
	int index;	/* id of this frame for user space */

	/* buf fd */
	int fd;

	/*
	 * input or output info
	 * w <= 0xFFFF
	 * h <= 0xFFFF
	 */
	unsigned int w;
	unsigned int h;
	unsigned int paddr[BT1120TX_FRME_MAX_PLANES];
	/*
	 * if stride = 0, cal by driver
	 * stride[x] <= 0xFFFF
	 */
	unsigned int stride[BT1120TX_FRME_MAX_PLANES];

	/* config file info, just valid for input dev node */
	unsigned int cfg_paddr;
	unsigned int cfg_size;

	/* time stamp of this hw module when dq */
	struct timeval tv_this;
	/* time stamp when vin, may not exist */
	struct timeval tv_vin;
};

# if 0
int bt1120_enc_init(BT1120_Tx_Config * txConfig);
u32 bt1120Enc_GetNoBankRdyCnt(void);
u32 bt1120Enc_GetBankReuseCnt(void);
u32 bt1120Enc_GetEncDoneCnt(void);
u32 bt1120Enc_GetBusState(void);
void bt1120Enc_EncClr(BT1120_Tx_Config *txConfig, u32 val);
void bt1120Enc_set_bank_rdy(BT1120_Tx_Config *txConfig, u32 rdy_index);
u32 bt1120Enc_get_bank_rdy(BT1120_Tx_Config *txConfig, u32 rdy_index);
#endif

#ifdef __cplusplus
}
#endif

#endif /* _TS_BT1120TX_H_ */
/****************************************************************************
 * Copyright (C) 2021,All rights reserved.
 * Version      : v1.0
 * Description  : bt1120 tx driver, YUV420 and RGB888 fromat is supported.
 ****************************************************************************/

#define pr_fmt(fmt)	"bt1120tx_drv: " fmt
//#include <stdlib.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/reset.h>
#include <linux/delay.h>

#include <linux/interrupt.h>
#include <linux/mutex.h>

#include <linux/miscdevice.h>
#include <linux/of_reserved_mem.h>
#include <linux/dma-mapping.h>
#include <linux/printk.h>
#include <asm-generic/io.h>

#include <linux/uaccess.h>
#include <linux/slab.h> //kzalloc

#include "ts_bt1120tx.h"


#ifdef DEBUG
static int bt_debug_level = 5;

#define bt_debug(level, fmt, args...)				\
	do {							\
		if (bt_debug_level >= level)			\
			pr_debug("%s:%d: " fmt,	\
				__func__, __LINE__, ##args);	\
	} while (0)
#else
#define bt_debug(level, fmt, args...) pr_debug(fmt, ##args)
#endif

#define bt_debug_enter() bt_debug(5, "enter\n")
#define bt_debug_leave() bt_debug(5, "leave\n")

#define bt_err(fmt, args...)				\
		pr_err("%s:%d: " fmt,		\
		       __func__, __LINE__, ##args)

#define bt_err_limited(fmt, args...)			\
		printk_ratelimited(KERN_ERR "%s:%d: " fmt,	\
		       __func__, __LINE__, ##args)

#define bt_info(fmt, args...)				\
		pr_info("%s:%d: " fmt,		\
		       __func__, __LINE__, ##args)



/*
 * outstanding == 4 ,
 * support interleaving, 16bit or 8bit
 * support 6 frame buffer,
 * support read 128 byte Y,
 * support image reversal
 */

#define SETBIT(reg, bit) \
			(reg = ((reg) | ((0x00000001) << (bit))))
#define RESETBIT(reg, bit) \
			(reg = ((reg) & (~(0x00000001 << (bit)))))
#define RESET2BIT(reg, bit) \
			(reg = ((reg) & (~(0x00000003 << (bit)))))
#define RESET3BIT(reg, bit) \
			(reg = ((reg) & (~(0x00000007 << (bit)))))
#define GETBIT(reg, bit) \
			((reg) & ((0x00000001) << (bit)))

#define TRUE						(1)
#define FALSE						(0)
#define ERROR						(-1)

#define ENC_SFT_RST					(1 << 20)

// bus state, readonly
#define DISPLAY_Y_CAP_LESS_ERR		(1 << 0)
#define DISPLAY_Y_CAP_MORE_ERR		(1 << 4)
#define DISPLAY_UV_CAP_LESS_ERR		(1 << 8)
#define DISPLAY_UV_CAP_MORE_ERR		(1 << 12)
#define ENC_LOST					(1 << 16)

// enc status clear, bus error and interrupt count
#define INT_CNT_CLR					(1 << 0)
#define BUS_STATE_CLR				(1 << 4)

// RGB2YUV
#if 0
//default register value..
#define RGB2YUV_PARA1_DEF			(0x132 | (0x259 << 16))
#define RGB2YUV_PARA2_DEF			(0x74 | (0x76A << 16))
#define RGB2YUV_PARA3_DEF			(0x6D9 | (0x1BE << 16))
#define RGB2YUV_PARA4_DEF			(0x275 | (0x5F1 << 16))
#define RGB2YUV_PARA5_DEF			(0x79A)
#else
#if 1
/*
 * #define RGB2YUV_PARA1_DEF			(0x132 | (0x259 << 16))
 * #define RGB2YUV_PARA2_DEF			(0x74 | (0x755 << 16))
 * #define RGB2YUV_PARA3_DEF			(0x6AE | (0x200 << 16))
 * #define RGB2YUV_PARA4_DEF			(0x200 | (0x654 << 16))
 * #define RGB2YUV_PARA5_DEF			(0x7AE)
 */

//good rather than default val.
#define RGB2YUV_PARA1_DEF			(0x132 | (0x259 << 16))
#define RGB2YUV_PARA2_DEF			(0x74 | (0xf55 << 16))
#define RGB2YUV_PARA3_DEF			(0xeAE | (0x200 << 16))
#define RGB2YUV_PARA4_DEF			(0x200 | (0xe54 << 16))
#define RGB2YUV_PARA5_DEF			(0xfAE)

#else
#define RGB2YUV_PARA1_DEF			(0x132 | (0x259 << 16))
#define RGB2YUV_PARA2_DEF			(0x74 | (0x4ad << 16))
#define RGB2YUV_PARA3_DEF			(0x553 | (0x200 << 16))
#define RGB2YUV_PARA4_DEF			(0x200 | (0x5ad << 16))
#define RGB2YUV_PARA5_DEF			(0x453)
#endif
#endif

#define ENC_BANK0_ADDR_BASE			(0x30000000)

#define ENC_REQ_WAIT_DEF			(0)//(10)	// 0 ~ 65536
#define AXI_ARQOS_DEF				(0)//(12) // 0 ~ 15

typedef struct _Enc_req_wait {
	u32 enc_req_wait;		// [0:15] req interval
	u32 axi_arqos;			// [16:19] aix bus qos signal
} Enc_req_wait;

enum _int_status {
	// interrupt status
	INT_ENC_DONE_INT = 0,
	INT_BANK_REUSE_INT = 4,
	INT_NO_BANK_RDY_INT = 8,
};
typedef enum _int_ena_clr {
	// interrupt enable
	INT_ENC_DONE_INT_ENA = 0,
	INT_BANK_REUSE_INT_ENA = 4,
	INT_NO_BANK_RDY_INT_ENA = 8,
	// interrupt clean
	INT_ENC_DONE_INT_CLR = 16,
	INT_BANK_REUSE_INT_CLR = 20,
	INT_NO_BANK_RDY_INT_CLR = 24,
} e_int_ena_clr;

enum bt1120_8bit_mode {
	ENC_16BIT_MODE = 0,
	ENC_8BIT_MODE = 1,
};

//enc ctrl freq
enum bt1120_enc_freq {
	ENC_FREQ_720P_25P = 0,
	ENC_FREQ_720P_30P = 1,
	ENC_FREQ_720P_50P = 2,
	ENC_FREQ_720P_60P = 3,
	ENC_FREQ_1080P_25P_50P = 0,
	ENC_FREQ_1080P_30P_60P = 1,
};

enum bt1120_enc_mode {
	ENC_MODE_16BIT_Y_HIGH = 0,
	ENC_MODE_16BIT_UV_HIGH = 1,
	ENC_MODE_8BIT_Y_FIRST = 0,
	ENC_MODE_8BIT_UV_FIRST = 1,
};

enum bt1120_enc_ctrl {
	VIDEO_OUT_EN = 0,			// [0] high valid
	BT1120_ENC_RANGE = 1,
	// [1] amplitude 0:YUV=[1:254] 1:Y=[16,235] UV=[16,240]
	BT1120_ENC_SIZE = 4,
	// [4] 0:720p(1280x720) 1:1080p(1920x1080)
	BT1120_ENC_FREQ = 8,
	// [8:9] 720p: 0:25p 1:30p 2:50p 3:60p
	BT1120_ENC_FREQ_HI = 9,
	//1080P: 0:25p(74.25Mhz)/50p(148.5Mhz) 1:30p/60p(148.5Mhz)
	BT1120_ENC_MODE = 12,
	// [12] yuv output format
	// 16bit: 0: Y(high 8bit) UV(low 8bit)  1: UV(high 8bit)Y
	// 8bit:  0:Y output first, UV second  1: UV output first, Y second
	BT1120_ENC_CT = 13,
	// [13] select input data 0: from DDR  1: test colour bar.
	BT1120_8BIT_OUT_SEL = 20,
	// [20] 0: select high 8bit output 1: select low 8bit output
	BT1120_8BIT_NOTSTD = 21,
	// [21] 8bit sync mode: 1: not standard 0: standard
	BT1120_8BIT_MODE = 22,
	// [22] encode mode 1: 8bit 0: 16bit
};

enum img_turn_mode {
	NORMAL = 0,
	FLIP_HZ,
	FLIP_VT,
	FLIP_VT_HZ,
};

enum export_en {
	EXPORT_AMPLITUDE_LIMIT_EN = 0,
	EXPORT_AMPLITUDE_LIMIT_DIS = 1,
};

enum data_down_ctrl {
	DISPLAY_WRAP_WORK_EN = 0,	// [0] 1: enable
	UV_DDR_MODE = 1,			// [1] 1:yuv420 0:rgb
	IMG_TURN_MODE = 4,
	// [4:5] 0:normal 1:flip HZ 2:flip VT 3:flip HZ and VT

	ENC_BANK0_RDY = 8,			// [8] bank0 data ready
	ENC_BANK3_RDY = 9,			// [9]
	ENC_BANK1_RDY = 12,			// [12]
	ENC_BANK4_RDY = 13,			// [13]
	ENC_BANK2_RDY = 16,			// [16]
	ENC_BANK5_RDY = 17,			// [17]
	EXPORT_EN = 18,
	// [18] 1: amplitude not limit 0: limit
	FRAME_INFO_EN = 19,
	// [19] 1: 128 Y insert frame_info 0: not insert
	ENC_SFT_FST = 20,			// [20] soft reset, high valid
	BANK_NUM = 21,				// [21:23] frame buffer numbers
};

enum resolution_mode {
	ENC_8BIT_720P_25P = 0,
	ENC_8BIT_720P_30P,
	ENC_8BIT_720P_50P,
	ENC_8BIT_720P_60P,

	ENC_8BIT_1080P_25P,
	ENC_8BIT_1080P_30P,
	ENC_8BIT_1080P_50P,
	ENC_8BIT_1080P_60P,

	ENC_16BIT_720P_25P,
	ENC_16BIT_720P_30P,
	ENC_16BIT_720P_50P,
	ENC_16BIT_720P_60P,

	ENC_16BIT_1080P_25P,
	ENC_16BIT_1080P_30P,
	ENC_16BIT_1080P_50P,
	ENC_16BIT_1080P_60P,
};

enum uv_ddr_mode {
	SOURCE_DATA_IS_RGB = 0,		// RGB 0888
	SOURCE_DATA_IS_YUV420 = 1,	// YUV420 NV12
};

enum bank_num {
	BANK_NUM_1 = 1,
	BANK_NUM_2,
	BANK_NUM_3,
	BANK_NUM_4,
	BANK_NUM_5,
	BANK_NUM_6,
	BANK_NUM_MAX = 6,
};

typedef struct _BT1120_Tx_Config {
	enum bank_num bank_num;
	u8 cur_bank_index;
	u32 frame_index;
	enum uv_ddr_mode ddr_mode;		// yuv420 or rgb
	bool test_colour_bar;
	enum resolution_mode res_mode ;	// 720P or 1080P
	enum img_turn_mode turn_mode;
	u8 pix_bits;
	u32 img_size;
	enum bt1120_8bit_mode export_bit_mode;
	enum bt1120_enc_mode export_data_mode;
	bool sync_notstd_8bit;
	bool low_8bit_output;
	bool uv_output_first;
	bool amplitude;
	bool insert_128_y;

	void __iomem *mem_base;
	void  *dma_vaddr;
	void  *bank_vaddr[6];
	u32	  dma_size;
	dma_addr_t dma_handler;

	u32 *enc_bank_addr[6]; // 32 bit system.

	// ctrl regs value
	u32 data_down_ctrl;
	u32 enc_req_wait;
	u32 bt1120_enc_ctrl;

	// readonly regs
	u32 enc_done_cnt;
	u32 bank_reuse_cnt;
	u32 no_bank_rdy_cnt;
	u32 bus_state;

	u32 enc_clr_val;		// clear bus state and interrupt count

	u32 info_bank0[32];
	u32 info_bank1[32];
	u32 info_bank2[32];
	u32 info_bank3[32];
	u32 info_bank4[32];
	u32 info_bank5[32];

	//tmp
	u32 int_ena_clr;
	u32 int_status;
	u32 int_cnt0;
	u32 int_cnt1;
	u32 int_cnt2;
	u32 rgb2yuv_para1;			// 0x344
	u32 rgb2yuv_para2;
	u32 rgb2yuv_para3;
	u32 rgb2yuv_para4;
	u32 rgb2yuv_para5;

} BT1120_Tx_Config;


typedef struct _BT1120_Tx_Regs {
	u32 data_down_ctrl;		// 0x000
	u32 enc_bank0;			// fb0 base addr
	u32 enc_bank1;
	u32 enc_bank2;

	u32 enc_req_wait;
	u32 bt1120_enc_ctrl;
	u32 int_ena_clr;
	u32 reserved_0;

	u32 int_status;
	u32 int_cnt0;
	// ro. complete count. though int_cnt_clr clear
	u32 int_cnt1;			// ro. bank reuse count
	u32 int_cnt2;			// ro. no frame for read count

	u32 enc_clr;
	u32 bus_state;
	u32 enc_bank3;			// fb3 base addr
	u32 enc_bank4;
	u32 enc_bank5;			// 0x40

	u32 info_bank0[32];
	// fb0 information, byte0 ~ byte127
	u32 info_bank1[32];
	u32 info_bank2[32];
	u32 info_bank3[32];
	u32 info_bank4[32];
	u32 info_bank5[32];

	u32 rgb2yuv_para1;			// 0x344
	u32 rgb2yuv_para2;
	u32 rgb2yuv_para3;
	u32 rgb2yuv_para4;
	u32 rgb2yuv_para5;

} BT1120_Tx_Regs;

//#define TEST_RGB
static BT1120_Tx_Regs *tx_regs;//(struct _BT1120_Tx_Regs *)tx_regs;
struct ts_bt1120tx *g_bt_tx;

static u32 ReadReg32(u32 *addr)
{
	return readl(addr);
}

static void WriteReg32(u32 *addr, u32 value)
{
	writel(value, addr);
}

u32 bt1120Enc_GetEncDoneCnt(void)
{
	return ReadReg32(&tx_regs->int_cnt0);
}

u32 bt1120Enc_GetBankReuseCnt(void)
{
	return ReadReg32(&tx_regs->int_cnt1);
}

u32 bt1120Enc_GetNoBankRdyCnt(void)
{
	return ReadReg32(&tx_regs->int_cnt2);
}

u32 bt1120Enc_GetBusState(void)
{
	u32 bus_state = ReadReg32(&tx_regs->bus_state);

	if (bus_state & DISPLAY_Y_CAP_LESS_ERR) {
		bt_debug(2, "%p 0x%08x: BUS STATE: display y cap less error !\n",
					&tx_regs->bus_state, bus_state);
	}
	if (bus_state & DISPLAY_Y_CAP_MORE_ERR) {
		bt_debug(2, "%p 0x%08x: BUS STATE: display y cap more error !\n",
					&tx_regs->bus_state, bus_state);
	}
	if (bus_state & DISPLAY_UV_CAP_LESS_ERR) {
		bt_debug(2, "%p 0x%08x: BUS STATE: display uv cap less error !\n",
					&tx_regs->bus_state, bus_state);
	}
	if (bus_state & DISPLAY_UV_CAP_MORE_ERR) {
		bt_debug(2, "%p 0x%08x: BUS STATE: display uv cap more error !\n",
					&tx_regs->bus_state, bus_state);
	}
	if (bus_state & ENC_LOST) {
		bt_debug(2, "%p 0x%08x: BUS STATE: enc lost error !\n",
					&tx_regs->bus_state, bus_state);
	}

	return bus_state;
}

void bt1120Enc_EncClr(BT1120_Tx_Config *txCfg, u32 val)
{
	txCfg->enc_clr_val = 0;

	if (val & BUS_STATE_CLR)
		txCfg->enc_clr_val |= BUS_STATE_CLR;

	if (val & INT_CNT_CLR)
		txCfg->enc_clr_val |= INT_CNT_CLR;


	WriteReg32(&tx_regs->enc_clr, txCfg->enc_clr_val);
}

void bt1120Enc_AXI_Config(BT1120_Tx_Config *txCfg)
{
	txCfg->enc_req_wait = ENC_REQ_WAIT_DEF | (AXI_ARQOS_DEF << 16);
	WriteReg32(&tx_regs->enc_req_wait, txCfg->enc_req_wait);
	bt_debug(2, "%p: 0x%08x : AXI configure.\r\n",
				&tx_regs->enc_req_wait, txCfg->enc_req_wait);
}

u32 bt1120Enc_GetIntr(void)
{
	return ReadReg32(&tx_regs->int_status);
}

void bt1120Enc_EnaIntr(e_int_ena_clr int_ena_bit)
{
	u32 ena_clr_val = ReadReg32(&tx_regs->int_ena_clr);

	SETBIT(ena_clr_val, int_ena_bit);
	WriteReg32(&tx_regs->int_ena_clr, ena_clr_val);
}
void bt1120Enc_EnaIntr_enable(u32 enable)
{
	//u32 ena_clr_val = ReadReg32(&tx_regs->int_ena_clr);

	WriteReg32(&tx_regs->int_ena_clr, enable);
}

u32 bt1120Enc_ClrIntr(u32 intrStatus)
{
	u32 clear_val = ReadReg32(&tx_regs->int_ena_clr);

	// clear interrupt
	if (intrStatus == 0)
		intrStatus = bt1120Enc_GetIntr();

	if (GETBIT(intrStatus, INT_ENC_DONE_INT))
		clear_val |= BIT(INT_ENC_DONE_INT_CLR);

	if (GETBIT(intrStatus, INT_BANK_REUSE_INT))
		clear_val |= BIT(INT_BANK_REUSE_INT_CLR);

	if (GETBIT(intrStatus, INT_NO_BANK_RDY_INT))
		clear_val |= BIT(INT_NO_BANK_RDY_INT_CLR);

	WriteReg32(&tx_regs->int_ena_clr, clear_val);

	return 0;
}

void bt1120_tx_irqhandler(int32_t idx)
{
	u32 status = bt1120Enc_GetIntr();

	// TODO... frame buffers ping-pang.
	bt_debug(7, "*****************interrupt tx******************\r\n");

	if (GETBIT(status, INT_ENC_DONE_INT)) {
		bt_debug(7, "intr: enc done.\r\n");
		//setting next buffer

	}
	if (GETBIT(status, INT_BANK_REUSE_INT)) {
		bt_debug(7, "intr: bank reuse.\r\n");
		//setting next buffer
	}
	if (GETBIT(status, INT_NO_BANK_RDY_INT)) {
		bt_debug(7, "intr: no bank ready.\r\n");
		//
	}

	bt1120Enc_ClrIntr(status);
}

void config_rgb2yuv_para(BT1120_Tx_Regs *tx_regs)
{
	WriteReg32(&tx_regs->rgb2yuv_para1, RGB2YUV_PARA1_DEF);
	WriteReg32(&tx_regs->rgb2yuv_para2, RGB2YUV_PARA2_DEF);
	WriteReg32(&tx_regs->rgb2yuv_para3, RGB2YUV_PARA3_DEF);
	WriteReg32(&tx_regs->rgb2yuv_para4, RGB2YUV_PARA4_DEF);
	WriteReg32(&tx_regs->rgb2yuv_para5, RGB2YUV_PARA5_DEF);
	bt_debug(2, "%p: 0x%08x :RGB2YUV para configure.\r\n",
		&tx_regs->rgb2yuv_para1, RGB2YUV_PARA1_DEF);
}

void bt1120_enc_reset(BT1120_Tx_Regs *tx_regs)
{
	u32 state = ReadReg32(&tx_regs->data_down_ctrl);

	state |= ENC_SFT_RST;
	WriteReg32(&tx_regs->data_down_ctrl, state);
}

void bt1120Enc_output_disable(BT1120_Tx_Config *txCfg,
		BT1120_Tx_Regs *tx_regs)
{
	// disable video output.
	RESETBIT(txCfg->bt1120_enc_ctrl, VIDEO_OUT_EN);
	WriteReg32(&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
	bt_debug(2, "%p: 0x%08x : disable video output.\r\n",
		&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
}

void bt1120Enc_bus_enable(BT1120_Tx_Config *txCfg)
{
	//1. enable bus
	SETBIT(txCfg->data_down_ctrl, DISPLAY_WRAP_WORK_EN);
	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(2, "%p: 0x%08x : bus enable.\r\n",
		&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
}

void bt1120Enc_ddr_mode(BT1120_Tx_Config *txCfg)
{
	//2.config ddr_mode rgb or yuv420
	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);
	if (txCfg->ddr_mode == SOURCE_DATA_IS_RGB) {
		RESETBIT(txCfg->data_down_ctrl, UV_DDR_MODE);
		txCfg->pix_bits = 32; // orgb ?

		//2.1. configure rgb2yuv
		config_rgb2yuv_para(tx_regs);
	} else if (txCfg->ddr_mode == SOURCE_DATA_IS_YUV420) {
		SETBIT(txCfg->data_down_ctrl, UV_DDR_MODE);
		txCfg->pix_bits = 12;
	}
	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(2, "%p: 0x%08x : pix_bits=%d configure ddr mode.\r\n",
		&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
		txCfg->pix_bits);
}

void bt1120Enc_amplitude_limit(BT1120_Tx_Config *txCfg)
{
	//3. amplitude limit, Y[16:235] UV[16:240].
	if (txCfg->amplitude) {
		txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);
		txCfg->bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
		RESETBIT(txCfg->data_down_ctrl, EXPORT_EN);
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_RANGE);
		WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
		WriteReg32(&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
		bt_debug(2, "%p: 0x%08x \r\n %p:0x%08x: amplitude limit enable.\r\n",
			&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
			&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
	}
}

void bt1120Enc_res_freq(BT1120_Tx_Config *txCfg)
{
	//4. configure res size and freq
	txCfg->bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
	RESET2BIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_FREQ);

	switch (txCfg->res_mode) {
	case ENC_8BIT_720P_25P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;
	case ENC_8BIT_720P_30P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_720P_30P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;
	case ENC_8BIT_720P_50P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_720P_50P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;
	case ENC_8BIT_720P_60P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_720P_60P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;

	case ENC_8BIT_1080P_25P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;
	case ENC_8BIT_1080P_30P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_1080P_30P_60P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;
	case ENC_8BIT_1080P_50P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;
	case ENC_8BIT_1080P_60P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_1080P_30P_60P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_8BIT_MODE;
		break;

	case ENC_16BIT_720P_25P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	case ENC_16BIT_720P_30P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_720P_30P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	case ENC_16BIT_720P_50P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_720P_50P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	case ENC_16BIT_720P_60P:
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_720P_60P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;

	case ENC_16BIT_1080P_25P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	case ENC_16BIT_1080P_30P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_1080P_30P_60P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	case ENC_16BIT_1080P_50P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	case ENC_16BIT_1080P_60P:
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE);
		txCfg->bt1120_enc_ctrl |=
			(ENC_FREQ_1080P_30P_60P << BT1120_ENC_FREQ);
		txCfg->export_bit_mode = ENC_16BIT_MODE;
		break;
	}

	if (txCfg->bt1120_enc_ctrl & (0x01 << BT1120_ENC_SIZE)) // 1080p
		txCfg->img_size = (1920 * 1080 * txCfg->pix_bits) / 8;
	else
		txCfg->img_size = (1280 * 720 * txCfg->pix_bits) / 8;

	WriteReg32(&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
	bt_debug(2, "%p: 0x%08x : ENC FREQ: enc_bit_mode=%s img_size=0x%x.\r\n",
		&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl,
		txCfg->export_bit_mode == ENC_16BIT_MODE ? "16BIT" : "8BIT",
		txCfg->img_size);
}

void bt1120Enc_turn_mode(BT1120_Tx_Config *txCfg)
{
	//5. configure img_turn_mode
	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);
	RESET2BIT(txCfg->data_down_ctrl, IMG_TURN_MODE);

	switch (txCfg->turn_mode) {
	case NORMAL:
		RESET2BIT(txCfg->data_down_ctrl, IMG_TURN_MODE);
		break;
	case FLIP_HZ:
		SETBIT(txCfg->data_down_ctrl, IMG_TURN_MODE);
		break;
	case FLIP_VT:
		SETBIT(txCfg->data_down_ctrl, IMG_TURN_MODE + 1);
		break;
	case FLIP_VT_HZ:
		SETBIT(txCfg->data_down_ctrl, IMG_TURN_MODE);
		SETBIT(txCfg->data_down_ctrl, IMG_TURN_MODE + 1);
		break;
	}

	//txCfg->data_down_ctrl |= (txCfg->turn_mode << IMG_TURN_MODE);
	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(2, "%p: 0x%08x : configure turn mode=%d.\r\n",
			&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
			txCfg->turn_mode);
}

u32 bt1120Enc_get_bank_rdy(BT1120_Tx_Config *txCfg, u32 rdy_index)
{
	int rdy_val;

	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);
	if (rdy_index < 3) {
		rdy_val =
			GETBIT(txCfg->data_down_ctrl,
				ENC_BANK0_RDY + (rdy_index * 4));
	} else {
		rdy_val =
			GETBIT(txCfg->data_down_ctrl,
				ENC_BANK3_RDY + (rdy_index * 4));
	}

	return rdy_val;
}

void bt1120Enc_clean_bank_rdy(BT1120_Tx_Config *txCfg, u32 rdy_index)
{
	int i;

	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);

	for (i = 0; i < txCfg->bank_num; i++) {
		if (rdy_index == i) {
			if (i < 3)
				RESETBIT(txCfg->data_down_ctrl,
					ENC_BANK0_RDY + (i * 4));
			else
				RESETBIT(txCfg->data_down_ctrl,
					ENC_BANK3_RDY + (i * 4));

		}
	}

	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(7, "%p: 0x%08x : clean bank ready=%d.\r\n",
			&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
			rdy_index);
}

void bt1120Enc_set_bank_rdy(BT1120_Tx_Config *txCfg, u32 rdy_index)
{
	int i;

	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);

	for (i = 0; i < txCfg->bank_num; i++) {
		if (rdy_index == i) {
			if (i < 3)
				SETBIT(txCfg->data_down_ctrl,
					ENC_BANK0_RDY + (i * 4));
			else
				SETBIT(txCfg->data_down_ctrl,
					ENC_BANK3_RDY + (i * 4));

		}
	}

	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(7, "%p: 0x%08x : set bank ready=%d.\r\n",
			&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
			rdy_index);
}

void bt1120Enc_bank_config(BT1120_Tx_Config *txCfg, BT1120_Tx_Regs *tx_regs)
{
	int i;
	u32 *pBank0_addr = &tx_regs->enc_bank0;
	u32 *pBank3_addr = &tx_regs->enc_bank3;

	//6. configure frame buffer numbers and address.
	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);

	RESET3BIT(txCfg->data_down_ctrl, BANK_NUM);
	txCfg->data_down_ctrl |= (txCfg->bank_num << BANK_NUM);

	for (i = 0; i < txCfg->bank_num; i++) {
		#if 0
		txCfg->enc_bank_addr[i] =
			(u32 *)ENC_BANK0_ADDR_BASE
			 + (i * txCfg->img_size);
		#else
		txCfg->enc_bank_addr[i] =
			(u32 *)(uintptr_t)txCfg->dma_handler
			 + (i * txCfg->img_size);
		txCfg->bank_vaddr[i] = txCfg->dma_vaddr
			 + (i * txCfg->img_size);
		#endif
		if (i < 3) {
			SETBIT(txCfg->data_down_ctrl, ENC_BANK0_RDY + (i * 4));
			bt_debug(2, "%p: 0x%p : bank address %d.\n",
				pBank0_addr, txCfg->enc_bank_addr[i], i);
			WriteReg32(pBank0_addr++,
				(u32)(uintptr_t)txCfg->enc_bank_addr[i]);
		} else {
			SETBIT(txCfg->data_down_ctrl, ENC_BANK3_RDY + (i * 4));
			bt_debug(2, "%p: 0x%p : bank address %d.\n",
				pBank3_addr, txCfg->enc_bank_addr[i], i);
			WriteReg32(pBank3_addr++,
				(u32)(uintptr_t)txCfg->enc_bank_addr[i]);
		}
	}

	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(2, "%p: 0x%08x : bank number=%d.\r\n",
			&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
			txCfg->bank_num);
}

void bt1120Enc_framInfo_enable(BT1120_Tx_Config *txCfg,
		BT1120_Tx_Regs *tx_regs)
{
	//7. insert frame information by default.
	txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);
	if (txCfg->insert_128_y)
		SETBIT(txCfg->data_down_ctrl, FRAME_INFO_EN);
	else
		RESETBIT(txCfg->data_down_ctrl, FRAME_INFO_EN);

	WriteReg32(&tx_regs->data_down_ctrl, txCfg->data_down_ctrl);
	bt_debug(2, "%p: 0x%08x : insert 128 Y into frame_info=%d.\r\n",
		&tx_regs->data_down_ctrl, txCfg->data_down_ctrl,
		txCfg->insert_128_y);
}

void bt1120Enc_export_config(BT1120_Tx_Config *txCfg)
{
	//8. configure export bits
	txCfg->bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
	if (txCfg->export_bit_mode == ENC_8BIT_MODE) {
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_8BIT_MODE);
		if (txCfg->sync_notstd_8bit) {
			// sync not standard
			SETBIT(txCfg->bt1120_enc_ctrl, BT1120_8BIT_NOTSTD);
		} else {
			// sync standard
			RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_8BIT_NOTSTD);
			// standard
		}

		if (txCfg->low_8bit_output) {
			//low 8bit output
			SETBIT(txCfg->bt1120_enc_ctrl, BT1120_8BIT_OUT_SEL);
		} else {
			//high 8bit output
			RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_8BIT_OUT_SEL);
		}

		if (txCfg->uv_output_first) {
			//1:UV output first
			SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_MODE);
		} else {
			//0:Y output first
			RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_MODE);
		}
	} else {
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_8BIT_MODE);

		if (txCfg->uv_output_first) {
			//1:UV(high 8bit)
			SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_MODE);
		} else {
			//0:Y(high 8bit)
			RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_MODE);
		}
	}
	WriteReg32(&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
	bt_debug(2, "%p: 0x%08x : configure export 8bit/16bit mode.\r\n",
			&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
}

void bt1120Enc_input_source(BT1120_Tx_Config *txCfg, BT1120_Tx_Regs *tx_regs)
{
	//9. read from ddr
	txCfg->bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
	if (txCfg->test_colour_bar)
		SETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_CT);
		// test colour bar.
	else
		RESETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_CT);


	WriteReg32(&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
	bt_debug(2, "%p: 0x%08x : data from ddr=%d.\r\n",
			&tx_regs->bt1120_enc_ctrl,
			txCfg->bt1120_enc_ctrl,
			!(txCfg->test_colour_bar));
}

void Bt1120Enc_output_enable(BT1120_Tx_Config *txCfg, BT1120_Tx_Regs *tx_regs)
{
	//10. final configure output enable
	txCfg->bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
	SETBIT(txCfg->bt1120_enc_ctrl, VIDEO_OUT_EN);
	WriteReg32(&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
	bt_debug(2, "%p: 0x%08x : ENC output enable.\r\n",
			&tx_regs->bt1120_enc_ctrl, txCfg->bt1120_enc_ctrl);
}

int bt1120_debug(BT1120_Tx_Config *txCfg, BT1120_Tx_Regs *tx_regs)
{
	static BT1120_Tx_Config config;
	int i = 0;

	config.data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);// 0x000
	bt_debug(2, "data_down_ctrl:0x%08x : reg 0x%08x\n",
			txCfg->data_down_ctrl, config.data_down_ctrl);

	config.enc_bank_addr[0] =
			(u32 *)(uintptr_t)ReadReg32(&tx_regs->enc_bank0);
	// fb0 base addr
	bt_debug(2, "enc_bank0: 0x%p : reg 0x%p\n",
			txCfg->enc_bank_addr[0], config.enc_bank_addr[0]);
	config.enc_bank_addr[1] =
			(u32 *)(uintptr_t)ReadReg32(&tx_regs->enc_bank1);
	bt_debug(2, "enc_bank1: 0x%p : reg 0x%p\n",
			txCfg->enc_bank_addr[1], config.enc_bank_addr[1]);
	config.enc_bank_addr[2] =
			(u32 *)(uintptr_t)ReadReg32(&tx_regs->enc_bank2);
	bt_debug(2, "enc_bank2: 0x%p : reg 0x%p\n",
			txCfg->enc_bank_addr[2], config.enc_bank_addr[2]);
	config.enc_req_wait = ReadReg32(&tx_regs->enc_req_wait);
	bt_debug(2, "enc_req_wait: 0x%08x : reg 0x%08x\n",
			txCfg->enc_req_wait, config.enc_req_wait);
	config.bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
	bt_debug(2, "bt1120_enc_ctrl:0x%08x : reg 0x%08x\n",
			txCfg->bt1120_enc_ctrl, config.bt1120_enc_ctrl);
	config.int_ena_clr = ReadReg32(&tx_regs->int_ena_clr);
	bt_debug(2, "int_ena_clr:0x%08x : reg 0x%08x\n",
			txCfg->int_ena_clr, config.int_ena_clr);
	config.int_status = ReadReg32(&tx_regs->int_status);
	bt_debug(2, "int_status: 0x%08x : reg 0x%08x\n",
			txCfg->int_status, config.int_status);

	config.int_cnt0 = ReadReg32(&tx_regs->int_cnt0);
	// ro. complete count. though int_cnt_clr clear
	bt_debug(2, "int_cnt0: 0x%08x : reg 0x%08x\n",
			txCfg->int_cnt0, config.int_cnt0);
	config.int_cnt1 = ReadReg32(&tx_regs->int_cnt1);
	// ro. bank reuse count
	bt_debug(2, "int_cnt1: 0x%08x : reg 0x%08x\n",
			txCfg->int_cnt1, config.int_cnt1);
	config.int_cnt2 = ReadReg32(&tx_regs->int_cnt2);
	// ro. no frame for read count
	bt_debug(2, "int_cnt2: 0x%08x : reg 0x%08x\n",
			txCfg->int_cnt2, config.int_cnt2);

	config.enc_clr_val = ReadReg32(&tx_regs->enc_clr);
	bt_debug(2, "enc_clr: 0x%08x : reg 0x%08x\n",
			txCfg->enc_clr_val, config.enc_clr_val);
	config.bus_state = ReadReg32(&tx_regs->bus_state);
	bt_debug(2, "bus_state: 0x%08x : reg 0x%08x\n",
			txCfg->bus_state, config.bus_state);
	// fb3 base addr
	config.enc_bank_addr[3] =
		(u32 *)(uintptr_t)ReadReg32(&tx_regs->enc_bank3);
	config.enc_bank_addr[4] =
		(u32 *)(uintptr_t)ReadReg32(&tx_regs->enc_bank4);
	config.enc_bank_addr[5] =
		(u32 *)(uintptr_t)ReadReg32(&tx_regs->enc_bank5);	// 0x40

/*
 * u32 info_bank0[32];// fb0 information, byte0 ~ byte127
 * u32 info_bank1[32];
 * u32 info_bank2[32];
 * u32 info_bank3[32];
 * u32 info_bank4[32];
 * u32 info_bank5[32];
 */
	for (i = 0; i < (sizeof(config.info_bank0) /
				 sizeof(config.info_bank0[0])); i++) {
		config.info_bank0[i] = ReadReg32(&tx_regs->info_bank0[i]);
		bt_debug(2, "info_bank0[%d]: 0x%08x : reg 0x%08x\n",
				i, txCfg->info_bank0[i], config.info_bank0[i]);
		config.info_bank1[i] = ReadReg32(&tx_regs->info_bank1[i]);
		bt_debug(2, "info_bank1[%d]: 0x%08x : reg 0x%08x\n",
				i, txCfg->info_bank1[i], config.info_bank1[i]);
		config.info_bank2[i] = ReadReg32(&tx_regs->info_bank2[i]);
		config.info_bank3[i] = ReadReg32(&tx_regs->info_bank3[i]);
		config.info_bank4[i] = ReadReg32(&tx_regs->info_bank4[i]);
		config.info_bank5[i] = ReadReg32(&tx_regs->info_bank5[i]);
	}

	config.rgb2yuv_para1 = ReadReg32(&tx_regs->rgb2yuv_para1);// 0x344
	bt_debug(2, "rgb2yuv_para1: 0x%08x : reg 0x%08x\n",
				txCfg->rgb2yuv_para1, config.rgb2yuv_para1);
	config.rgb2yuv_para2 = ReadReg32(&tx_regs->rgb2yuv_para2);
	bt_debug(2, "rgb2yuv_para2: 0x%08x : reg 0x%08x\n",
				txCfg->rgb2yuv_para2, config.rgb2yuv_para2);
	config.rgb2yuv_para3 = ReadReg32(&tx_regs->rgb2yuv_para3);
	bt_debug(2, "rgb2yuv_para3: 0x%08x : reg 0x%08x\n",
				txCfg->rgb2yuv_para3, config.rgb2yuv_para3);
	config.rgb2yuv_para4 = ReadReg32(&tx_regs->rgb2yuv_para4);
	bt_debug(2, "rgb2yuv_para4: 0x%08x : reg 0x%08x\n",
				txCfg->rgb2yuv_para4, config.rgb2yuv_para4);
	config.rgb2yuv_para5 = ReadReg32(&tx_regs->rgb2yuv_para5);
	bt_debug(2, "rgb2yuv_para5: 0x%08x : reg 0x%08x\n",
				txCfg->rgb2yuv_para5, config.rgb2yuv_para5);

	return 0;
}

int bt1120Enc_reWriteReg(BT1120_Tx_Regs *tx_regs)
{
	WriteReg32((void *)tx_regs + 0x00, 0x00611101);
	WriteReg32((void *)tx_regs + 0x04, 0x30000000);
	WriteReg32((void *)tx_regs + 0x08, 0x30800000);
	WriteReg32((void *)tx_regs + 0x0c, 0x31000000);
	WriteReg32((void *)tx_regs + 0x38, 0x31800000);
	WriteReg32((void *)tx_regs + 0x3c, 0x32000000);
	WriteReg32((void *)tx_regs + 0x40, 0x32800000);
	WriteReg32((void *)tx_regs + 0x10, 0x00000000);
	WriteReg32((void *)tx_regs + 0x44, 0x8a898887);
	WriteReg32((void *)tx_regs + 0x48, 0x8e8d8c8b);
	WriteReg32((void *)tx_regs + 0x4c, 0x9291908f);
	WriteReg32((void *)tx_regs + 0x50, 0x96959493);
	WriteReg32((void *)tx_regs + 0x54, 0x9a999897);
	WriteReg32((void *)tx_regs + 0x58, 0x9e9d9c9b);
	WriteReg32((void *)tx_regs + 0x5c, 0xa2a1a09f);
	WriteReg32((void *)tx_regs + 0x60, 0xa6a5a4a3);
	WriteReg32((void *)tx_regs + 0x64, 0xaaa9a8a7);
	WriteReg32((void *)tx_regs + 0x68, 0xa3adacab);
	WriteReg32((void *)tx_regs + 0x6c, 0xb2b1b0af);
	WriteReg32((void *)tx_regs + 0x70, 0xb6b5b4b3);
	WriteReg32((void *)tx_regs + 0x74, 0xbab9b8b7);
	WriteReg32((void *)tx_regs + 0x78, 0xbebdbcbb);
	WriteReg32((void *)tx_regs + 0x7c, 0xc2c1c0bf);
	WriteReg32((void *)tx_regs + 0x80, 0xc6c5c4c3);
	WriteReg32((void *)tx_regs + 0x84, 0xcac9c8c7);
	WriteReg32((void *)tx_regs + 0x88, 0xcecdcccb);
	WriteReg32((void *)tx_regs + 0x8c, 0xd2d1d0cf);
	WriteReg32((void *)tx_regs + 0x90, 0x00611101);
	WriteReg32((void *)tx_regs + 0x94, 0x00611101);
	WriteReg32((void *)tx_regs + 0x98, 0x00611101);
	WriteReg32((void *)tx_regs + 0x9c, 0x00611101);
	WriteReg32((void *)tx_regs + 0xa0, 0x00611101);
	WriteReg32((void *)tx_regs + 0xa4, 0x00611101);
	WriteReg32((void *)tx_regs + 0xa8, 0x00611101);
	WriteReg32((void *)tx_regs + 0xac, 0x00611101);
	WriteReg32((void *)tx_regs + 0xb0, 0x00611101);
	WriteReg32((void *)tx_regs + 0xb4, 0x00611101);
	WriteReg32((void *)tx_regs + 0xb8, 0x00611101);
	WriteReg32((void *)tx_regs + 0xbc, 0x00611101);
	WriteReg32((void *)tx_regs + 0xc0, 0x00611101);
	WriteReg32((void *)tx_regs + 0xc4, 0x00611101);
	WriteReg32((void *)tx_regs + 0xc8, 0x00611101);
	WriteReg32((void *)tx_regs + 0xcc, 0x00611101);
	WriteReg32((void *)tx_regs + 0xd0, 0x00611101);
	WriteReg32((void *)tx_regs + 0xd4, 0x00611101);
	WriteReg32((void *)tx_regs + 0xdc, 0x00611101);
	WriteReg32((void *)tx_regs + 0xe0, 0x00611101);
	WriteReg32((void *)tx_regs + 0xe4, 0x00611101);
	WriteReg32((void *)tx_regs + 0xe8, 0x00611101);
	WriteReg32((void *)tx_regs + 0xec, 0x00611101);
	WriteReg32((void *)tx_regs + 0xf0, 0x00611101);
	WriteReg32((void *)tx_regs + 0xf4, 0x00611101);
	WriteReg32((void *)tx_regs + 0xf8, 0x00611101);
	WriteReg32((void *)tx_regs + 0xfc, 0x00611101);
	WriteReg32((void *)tx_regs + 0x100, 0x00611101);
	WriteReg32((void *)tx_regs + 0x104, 0x00611101);
	WriteReg32((void *)tx_regs + 0x108, 0x00611101);
	WriteReg32((void *)tx_regs + 0x10c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x108, 0x00611101);
	WriteReg32((void *)tx_regs + 0x10c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x110, 0x00611101);
	WriteReg32((void *)tx_regs + 0x114, 0x00611101);
	WriteReg32((void *)tx_regs + 0x118, 0x00611101);
	WriteReg32((void *)tx_regs + 0x11c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x120, 0x00611101);
	WriteReg32((void *)tx_regs + 0x124, 0x00611101);
	WriteReg32((void *)tx_regs + 0x128, 0x00611101);
	WriteReg32((void *)tx_regs + 0x12c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x130, 0x00611101);
	WriteReg32((void *)tx_regs + 0x134, 0x00611101);
	WriteReg32((void *)tx_regs + 0x138, 0x00611101);
	WriteReg32((void *)tx_regs + 0x13c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x140, 0x00611101);
	WriteReg32((void *)tx_regs + 0x144, 0x00611101);
	WriteReg32((void *)tx_regs + 0x148, 0x00611101);
	WriteReg32((void *)tx_regs + 0x14c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x150, 0x00611101);
	WriteReg32((void *)tx_regs + 0x154, 0x00611101);
	WriteReg32((void *)tx_regs + 0x158, 0x00611101);
	WriteReg32((void *)tx_regs + 0x15c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x160, 0x00611101);
	WriteReg32((void *)tx_regs + 0x164, 0x00611101);
	WriteReg32((void *)tx_regs + 0x168, 0x00611101);
	WriteReg32((void *)tx_regs + 0x16c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x170, 0x00611101);
	WriteReg32((void *)tx_regs + 0x174, 0x00611101);
	WriteReg32((void *)tx_regs + 0x178, 0x00611101);
	WriteReg32((void *)tx_regs + 0x17c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x180, 0x00611101);
	WriteReg32((void *)tx_regs + 0x184, 0x00611101);
	WriteReg32((void *)tx_regs + 0x188, 0x00611101);
	WriteReg32((void *)tx_regs + 0x18c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x190, 0x00611101);
	WriteReg32((void *)tx_regs + 0x194, 0x00611101);
	WriteReg32((void *)tx_regs + 0x198, 0x00611101);
	WriteReg32((void *)tx_regs + 0x19c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x200, 0x00611101);
	WriteReg32((void *)tx_regs + 0x204, 0x00611101);
	WriteReg32((void *)tx_regs + 0x208, 0x00611101);
	WriteReg32((void *)tx_regs + 0x20c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x210, 0x00611101);
	WriteReg32((void *)tx_regs + 0x214, 0x00611101);
	WriteReg32((void *)tx_regs + 0x218, 0x00611101);
	WriteReg32((void *)tx_regs + 0x21c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x220, 0x00611101);
	WriteReg32((void *)tx_regs + 0x224, 0x00611101);
	WriteReg32((void *)tx_regs + 0x228, 0x00611101);
	WriteReg32((void *)tx_regs + 0x22c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x230, 0x00611101);
	WriteReg32((void *)tx_regs + 0x234, 0x00611101);
	WriteReg32((void *)tx_regs + 0x238, 0x00611101);
	WriteReg32((void *)tx_regs + 0x23c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x240, 0x00611101);
	WriteReg32((void *)tx_regs + 0x244, 0x00611101);
	WriteReg32((void *)tx_regs + 0x248, 0x00611101);
	WriteReg32((void *)tx_regs + 0x24c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x250, 0x00611101);
	WriteReg32((void *)tx_regs + 0x254, 0x00611101);
	WriteReg32((void *)tx_regs + 0x258, 0x00611101);
	WriteReg32((void *)tx_regs + 0x25c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x260, 0x00611101);
	WriteReg32((void *)tx_regs + 0x264, 0x00611101);
	WriteReg32((void *)tx_regs + 0x268, 0x00611101);
	WriteReg32((void *)tx_regs + 0x26c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x270, 0x00611101);
	WriteReg32((void *)tx_regs + 0x274, 0x00611101);
	WriteReg32((void *)tx_regs + 0x278, 0x00611101);
	WriteReg32((void *)tx_regs + 0x27c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x280, 0x00611101);
	WriteReg32((void *)tx_regs + 0x284, 0x00611101);
	WriteReg32((void *)tx_regs + 0x288, 0x00611101);
	WriteReg32((void *)tx_regs + 0x28c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x290, 0x00611101);
	WriteReg32((void *)tx_regs + 0x294, 0x00611101);
	WriteReg32((void *)tx_regs + 0x298, 0x00611101);
	WriteReg32((void *)tx_regs + 0x29c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2a0, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2a4, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2a8, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2ac, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2b0, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2b4, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2b8, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2bc, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2c0, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2c4, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2c8, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2cc, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2d0, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2d4, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2d8, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2dc, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2e0, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2e4, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2e8, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2ec, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2f0, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2f4, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2f8, 0x00611101);
	WriteReg32((void *)tx_regs + 0x2fc, 0x00611101);
	WriteReg32((void *)tx_regs + 0x300, 0x00611101);
	WriteReg32((void *)tx_regs + 0x304, 0x00611101);
	WriteReg32((void *)tx_regs + 0x308, 0x00611101);
	WriteReg32((void *)tx_regs + 0x30c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x310, 0x00611101);
	WriteReg32((void *)tx_regs + 0x314, 0x00611101);
	WriteReg32((void *)tx_regs + 0x318, 0x00611101);
	WriteReg32((void *)tx_regs + 0x31c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x320, 0x00611101);
	WriteReg32((void *)tx_regs + 0x324, 0x00611101);
	WriteReg32((void *)tx_regs + 0x328, 0x00611101);
	WriteReg32((void *)tx_regs + 0x32c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x330, 0x00611101);
	WriteReg32((void *)tx_regs + 0x334, 0x00611101);
	WriteReg32((void *)tx_regs + 0x338, 0x00611101);
	WriteReg32((void *)tx_regs + 0x33c, 0x00611101);
	WriteReg32((void *)tx_regs + 0x340, 0x00611101);
	WriteReg32((void *)tx_regs + 0x14, 0x00100101);
	WriteReg32((void *)tx_regs + 0x00, 0x00610101);

	WriteReg32((void *)tx_regs + 0x18, 0x00000111);
	return 0;
}

int bt1120_enc_hw_config(BT1120_Tx_Config *txCfg, BT1120_Tx_Regs *tx_regs)
{
#if 0
	u32 rdata;

	WriteReg32((void *)CGU_BASE + 0x38, 0x0);
	WriteReg32((void *)CGU_BASE + 0x3c, 0x0);

	rdata = ReadReg32((void *)CGU_BASE + 0x50);
#if 0
	while ((rdata & 0x80) != 0x80)
		rdata = ReadReg32((void *) CGU_BASE + 0x50);

#endif
	rdata = ReadReg32((void *)CGU_BASE + 0x88);
	WriteReg32((void *)CGU_BASE + 0x88, rdata | 0x01 << 0);
#endif

	bt1120Enc_output_disable(txCfg, tx_regs);
#if 1
	bt1120Enc_AXI_Config(txCfg);
	bt1120Enc_bus_enable(txCfg);
	bt1120Enc_ddr_mode(txCfg);
	bt1120Enc_amplitude_limit(txCfg);
	bt1120Enc_res_freq(txCfg);
	bt1120Enc_turn_mode(txCfg);
	bt1120Enc_bank_config(txCfg, tx_regs);
	bt1120Enc_framInfo_enable(txCfg, tx_regs);
	bt1120Enc_export_config(txCfg);
	bt1120Enc_input_source(txCfg, tx_regs);

	// enable interrupt
	bt1120Enc_EnaIntr(INT_ENC_DONE_INT_ENA);
	//bt1120Enc_EnaIntr(INT_BANK_REUSE_INT_ENA);
	//bt1120Enc_EnaIntr(INT_NO_BANK_RDY_INT_ENA);
#else
	bt1120Enc_reWriteReg(tx_regs);
#endif
	Bt1120Enc_output_enable(txCfg, tx_regs);

	//bt1120_debug(txCfg, tx_regs);

	return 0;
}

int bt1120_enc_init(BT1120_Tx_Config *txCfg)
{
	int ret;
#if 0
	void *handler;
	u32 base, irq;

	//bt1120_enc_reset(tx_regs);		// software reset first.

	ret = target_bt1120_init(1, &base, &irq, &handler);
	if (ret < 0 || ret >= CONFIG_BT1120_NUM)
		return ERROR;

	static struct IrqTableEntry Entry;

	Entry.Handler = handler;
	Entry.data = NULL;

	drv_irq_register(irq, &Entry);
	//drv_irq_enable(irq);  //debug  tx and rx all enable has GIC error.
#endif

	//txCfg->data_down_ctrl = ReadReg32(&tx_regs->data_down_ctrl);
	//txCfg->bt1120_enc_ctrl = ReadReg32(&tx_regs->bt1120_enc_ctrl);
	ret = bt1120_enc_hw_config(txCfg, tx_regs);

	return ret;
}


struct ts_bt1120tx {
	BT1120_Tx_Config txCfg;
	void __iomem *reg_base;
	struct clk *clk;
	uint64_t clk_rate; /* bus interface clock rate */
	struct device *dev;

	struct miscdevice	  misc_dev;

	/* elements used by ISR */
	struct completion complete;
	spinlock_t irq_lock;
	uint32_t irq_mask;
	uint32_t irq_status;
	uint32_t irq;

};

struct ts_bt1120tx_device_data {
	unsigned int revision;
};

static const struct ts_bt1120tx_device_data ts_bt1120tx_data = {
	.revision = 100,
};

//static BT1120_Tx_Config txCfg;

int ycbcr_exchange_rgb(u32 mode,
		u32 *r, u32 *g, u32 *b, u32 *y, u32 *cb, u32 *cr)
{
#if 0
	float yy, ccr, ccb;

	switch (mode) {
	case 2: //709	rgb => ycbcr
		yy  =  0.2126 * (*r) + 0.7154 * (*g) + 0.072 * (*b);
		ccb = -(0.1145 * (*r)) - 0.3855 * (*g) + 0.5 * (*b) + 128;
		ccr =  0.5 * (*r) - 0.4543 * (*g) - 0.0457 * (*b) + 128;
		if (yy > 0xff)
			yy = 0xff;
		if (yy < 0)
			yy = 0;

		if (ccb > 0xff)
			ccb = 0xff;
		if (ccb < 0)
			ccb = 0;

		if (ccr > 0xff)
			ccr = 0xff;
		if (ccr < 0)
			ccr = 0;

		*y = (u32)yy;
		*cb = (u32)ccb;
		*cr = (u32)ccr;
		break;

	case 1: //601 rgb => ycbcr
		yy  =  0.257 * (*r) + 0.564 * (*g) + 0.098 * (*b) + 16 + 0.5;
		ccb = -(0.148 * (*r)) - 0.291 * (*g) + 0.439 * (*b) + 128 + 0.5;
		ccr =  0.439 * (*r) - 0.368 * (*g) - 0.071 * (*b) + 128 + 0.5;
		if (yy > 0xff)
			yy = 0xff;
		if (yy < 0)
			yy = 0;

		if (ccb > 0xff)
			ccb = 0xff;
		if (ccb < 0)
			ccb = 0;

		if (ccr > 0xff)
			ccr = 0xff;
		if (ccr < 0)
			ccr = 0;

		*y = (u32)yy;
		*cb = (u32)ccb;
		*cr = (u32)ccr;
		bt_debug(2, "y=0x%x cb=0x%x cr=0x%x\r\n", *y, *cb, *cr);
		break;
	case 0: //601	ycbcr => rgb
		*r = 1.164 * (*y - 16) + 1.596 * (*cr - 128);
		*g = 1.164 * (*y - 16) - 0.392 *
				(*cb - 128) - 0.813 * (*cr - 128);
		*b = 1.164 * (*y - 16) + 2.017 * (*cb - 128);
		bt_debug(2, "r=0x%x g=0x%x b=0x%x\r\n", *r, *g, *b);
		break;
	}
#endif
	return 0;
}

int rgb_data_prepare(u32 *addr, u32 width, u32 height, u8 r, u8 g, u8 b)
{
	u32 i;
	u8 *buffer = (void *)(uintptr_t)addr;

	// 0RGB == RGB888
#if 0
	for (i = 0; i < width * height * 4; i += 4) {
		buffer[i] = 0;
		buffer[i + 1] = r;
		buffer[i + 2] = g;
		buffer[i + 3] = b;
	}
#else
	for (i = 0; i < width * height * 4; i += 4) {
		buffer[i] = b;
		buffer[i + 1] = g;
		buffer[i + 2] = r;
		buffer[i + 3] = 0;
	}
#endif
	return 0;
}

int yuv420_data_prepare(BT1120_Tx_Config *txCfg,
		u32 *addr, u32 width, u32 height, u8 y, u8 u, u8 v)
{
	//nv12 y... uvuv...
	u32 i, y_size = width * height;
	u8 *buffer = (void *)(uintptr_t)addr;

	for (i = 0; i < txCfg->img_size; i += 2) {
		if (i < y_size) {
			buffer[i] = y;
			buffer[i + 1] = y;
		} else {
			buffer[i] = u;
			buffer[i + 1] = v;
		}
	}

	return 0;
}
// ORGB == 32bit ABGR == 0:B 8:G 16:R 24:A 32
int generate_data(enum uv_ddr_mode is_yuv420, BT1120_Tx_Config *txCfg)
{
#if 1
	//u32 r = 0x50, g = 0xa0, b = 0x55;
	//u32 r = 0x85, g = 0x8a, b = 0x8f;
	u32 r = 0x40, g = 0x80, b = 0xe0;
	//u32 r = 0x11, g = 0x22, b = 0x33;
	//u32 r = 0xff, g = 0, b = 0;		// red   : 0x0000FF00
	//u32 r = 0, g = 0xff, b = 0;		// green
	//u32 r = 0, g = 0, b = 0xff;
	// blue  : 0xFF000000 => 0x00007700
	u32 y = 0x80, cb = 0x80, cr = 0x80;	// gray
	static u32 width = 1920, height = 1080;
	static int generated;

	if (GETBIT(txCfg->bt1120_enc_ctrl, BT1120_ENC_SIZE)) { // 1080P
		width = 1920;
		height = 1080;
	} else {
		width = 1280;
		height = 720;
	}
#endif

	if (bt1120Enc_get_bank_rdy(txCfg, txCfg->cur_bank_index) &&
					(txCfg->bank_num != BANK_NUM_1)) {
		bt_debug(7, "skip current bank %d\n", txCfg->cur_bank_index);
		//bt1120Enc_clean_bank_rdy(txCfg, txCfg->cur_bank_index);
		txCfg->cur_bank_index++;
		txCfg->cur_bank_index %= txCfg->bank_num;
	}

#if 1
	if (!(generated & (0x01 << txCfg->cur_bank_index)) &&
				(txCfg->test_colour_bar == FALSE)) {
		if (is_yuv420 == SOURCE_DATA_IS_YUV420) {
			ycbcr_exchange_rgb(1, &r, &g, &b, &y, &cb, &cr);
			yuv420_data_prepare(txCfg,
				txCfg->bank_vaddr[txCfg->cur_bank_index],
					width, height, y, cb, cr);
		} else {
			ycbcr_exchange_rgb(1, &r, &g, &b, &y, &cb, &cr);
			rgb_data_prepare(
				txCfg->bank_vaddr[txCfg->cur_bank_index],
					width, height, r, g, b);
		}
		generated |= 0x01 << txCfg->cur_bank_index;
	}
#endif

	bt1120Enc_set_bank_rdy(txCfg, txCfg->cur_bank_index);

	return 0;
}

/*
 * 74.25MHz RGB/YUV
 * YUV422 720P25 720P30 720P50 720P60 1080P25 1080P30
 *
 * 148.5MHz RGB/YUV
 * YUV422 1080P50 1080P60
 */

void prase_res(BT1120_Tx_Config *txCfg)
{

}


// bt1120rx only support 16bit data.
void bt1120tx_pre_config(struct ts_bt1120tx *bt_tx)
{
	BT1120_Tx_Config *txCfg = &bt_tx->txCfg;

	//user configure
	txCfg->test_colour_bar = FALSE;	// first test from colour-bar.
	txCfg->bank_num = BANK_NUM_2;//BANK_NUM_MAX;
	bt_tx->txCfg.cur_bank_index = 0;
	txCfg->turn_mode = NORMAL;//FLIP_VT_HZ; // flip hz and vt

	txCfg->amplitude = FALSE;//TRUE;

#ifndef TEST_RGB
	// YUV420 16BIT 1080P30
	txCfg->ddr_mode = SOURCE_DATA_IS_YUV420; // TEST OK.

	//txCfg->ddr_mode = SOURCE_DATA_IS_RGB;
	//TEST FAILED, RGB2YUV HAS ERROR.

	// ****** 74.25MHz ***** //
	//ENC_8BIT_720P_25P; //ok
	//ENC_8BIT_720P_30P; //ok
	//ENC_16BIT_720P_50P; //failed
	//ENC_16BIT_720P_60P; //failed
	//ENC_8BIT_1080P_25P; //failed
	//ENC_8BIT_1080P_30P; //failed
	//ENC_16BIT_1080P_30P; //failed
	//ENC_16BIT_1080P_25P; //failed

	txCfg->res_mode = ENC_16BIT_720P_30P;//ENC_16BIT_1080P_60P;
	//txCfg->res_mode = ENC_16BIT_1080P_30P;  //0k
	//txCfg->res_mode = ENC_8BIT_720P_25P;  //error
#else
	// RGB 8bit 720P60
	txCfg->ddr_mode = SOURCE_DATA_IS_RGB;
	/** interrupt **/
	//ENC_8BIT_1080P_30P; //failed
	//ENC_16BIT_1080P_30P; //failed
	//ENC_8BIT_720P_25P; //ok
	//ENC_8BIT_720P_30P; //ok
	//ENC_8BIT_720P_60P; //failed
	//ENC_16BIT_720P_60P; //failed
	//ENC_16BIT_720P_50P; //failed

	/** data gsg **/
	//ENC_16BIT_1080P_30P; //error
	/*txCfg->res_mode = ENC_16BIT_1080P_30P;*/
	//ENC_16BIT_720P_25P;//ENC_8BIT_1080P_25P;
	//txCfg->res_mode = ENC_16BIT_720P_25P;
	txCfg->res_mode = ENC_16BIT_720P_30P;
#endif

	txCfg->sync_notstd_8bit = 0;	// 0 default
	//txCfg->sync_notstd_8bit = 1;	// 0 default
	txCfg->low_8bit_output = 1;	// 0 default
	txCfg->uv_output_first = 0;	// 0 default
	txCfg->insert_128_y = FALSE;//TRUE;
}

void bt1120tx_prepare_data(BT1120_Tx_Config *txCfg)
{
	// write -> ready
	// done -> check-ready -> switch buffer
	// 30p test 5 minutes
	generate_data(txCfg->ddr_mode, txCfg);
	if (0 == (txCfg->frame_index % 30)) {
		txCfg->no_bank_rdy_cnt = bt1120Enc_GetNoBankRdyCnt();
		txCfg->bank_reuse_cnt = bt1120Enc_GetBankReuseCnt();
		txCfg->enc_done_cnt = bt1120Enc_GetEncDoneCnt();
		txCfg->bus_state = bt1120Enc_GetBusState();
		bt_debug(6,
	"no_bank_rdy_cnt=%d, bank_reuse_cnt=%d, enc_done_cnt=%d, bus_state=%d\n",
			txCfg->no_bank_rdy_cnt, txCfg->bank_reuse_cnt,
			txCfg->enc_done_cnt, txCfg->bus_state);

		bt1120Enc_EncClr(txCfg, BUS_STATE_CLR);
		bt1120Enc_EncClr(txCfg, INT_CNT_CLR);
	}
}

void ts_bt1120tx_change_bank(struct ts_bt1120tx *bt_tx)
{
		//bt_tx->txCfg.cur_bank_index += 1;
		//bt_tx->txCfg.cur_bank_index =
			//bt_tx->txCfg.cur_bank_index % bt_tx->txCfg.bank_num;

		//todo...
		//reinit_completion(&bt_tx->complete);

		//write data...
		bt1120tx_prepare_data(&bt_tx->txCfg);//todo
}

int bt1120tx_ioctl(struct platform_device *pdev)
{
	struct ts_bt1120tx *bt_tx = platform_get_drvdata(pdev);
	BT1120_Tx_Config *txCfg = &bt_tx->txCfg;

	u32 ret = 0;

	//case 1:
	bt1120tx_pre_config(bt_tx);
	ret = bt1120_enc_init(txCfg);
	//case 2:
	ts_bt1120tx_change_bank(bt_tx);

	return ret;
}

static irqreturn_t ts_isr(int irq, void *dev_id)
{

	struct ts_bt1120tx *bt_tx = dev_id;
	BT1120_Tx_Config *txCfg = &bt_tx->txCfg;
	irqreturn_t ret = IRQ_NONE;
	uint32_t status;
	//unsigned long flags;
	//uint32_t irq_status;
	//u8 tmp_index;

	//spin_lock_irqsave(&bt_tx->irq_lock, flags);
	spin_lock(&bt_tx->irq_lock);
	status = bt1120Enc_GetIntr();

	// TODO... frame buffers ping-pang.
	bt_debug(7, "*****************interrupt tx******************\r\n");

	if (GETBIT(status, INT_ENC_DONE_INT)) {
		bt_debug(6, "intr: enc done.\r\n");
		if (bt1120Enc_get_bank_rdy(txCfg, txCfg->cur_bank_index))
			bt1120Enc_clean_bank_rdy(txCfg, txCfg->cur_bank_index);
		bt_tx->txCfg.frame_index++;

		//setting next buffer
		//todo...
		//complete(&bt_tx->complete);
		ts_bt1120tx_change_bank(bt_tx);
	}
	if (GETBIT(status, INT_BANK_REUSE_INT)) {
		bt_debug(7, "intr: bank reuse.\r\n");
		//setting next buffer
		//todo...
		//complete(&bt_tx->complete);
		//ts_bt1120tx_change_bank(bt_tx);
	}
	if (GETBIT(status, INT_NO_BANK_RDY_INT)) {
		bt_debug(7, "intr: no bank ready.\r\n");
		//
	}

	bt1120Enc_ClrIntr(status);
	bt_tx->txCfg.int_status = status;
	//spin_unlock_irqrestore(&bt_tx->irq_lock, flags);
	spin_unlock(&bt_tx->irq_lock);

	ret = IRQ_HANDLED;
	return ret;
}

static int ts_bt1120tx_parse_dt(struct platform_device *pdev,
			struct ts_bt1120tx *bt_tx)
{
	struct resource *res;
	struct device *dev = &pdev->dev;
	//struct device_node *np = dev->of_node;
	struct reset_control *rstc;
	int ret;

	bt_tx->dev = &pdev->dev;

	//res
	//res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ts-bt1120tx");
	if (!res) {
		dev_err(&pdev->dev, "missing IO resource\n");
		return -ENODEV;
	}
	bt_tx->reg_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(bt_tx->reg_base))
		return PTR_ERR(bt_tx->reg_base);
	tx_regs = (struct _BT1120_Tx_Regs *)bt_tx->reg_base;
	dev_dbg(&pdev->dev, "res->start:0x%08x\n", (u32)res->start);

	//clk init todo...
	bt_tx->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(bt_tx->clk)) {
		dev_err(&pdev->dev, "Cannot claim BT1120tx clock.\n");
		ret = PTR_ERR(bt_tx->clk);
		goto io_unmap;
	}
	ret = clk_prepare_enable(bt_tx->clk);
	if (ret) {
		dev_err(&pdev->dev, "Cannot enable BT1120tx clock.\n");
		goto io_unmap;
	}
	bt_tx->clk_rate = clk_get_rate(bt_tx->clk);
	dev_info(&pdev->dev, "clock rate %lld\n", bt_tx->clk_rate);

	/* Obtain BT1120tx reset control */
	rstc =
	devm_reset_control_get_optional_exclusive(dev, "bt1120tx_global");
	if (IS_ERR(rstc)) {
		ret = PTR_ERR(rstc);
		dev_err(dev, "Cannot get BT1120tx reset.\n");
		goto out_disable_clk;
	}
	reset_control_assert(rstc);
	udelay(5);
	reset_control_deassert(rstc);

	//irq
	//bt_tx->irq = platform_get_irq_byname(pdev, TS_BT1120TX_NAME);
	bt_tx->irq = platform_get_irq(pdev, 0);
	if (bt_tx->irq < 0) {
		dev_err(&pdev->dev, "no irq defined\n");
		ret = bt_tx->irq;
		goto reset_failed;
	}
	dev_dbg(&pdev->dev, " irq is %d\n", bt_tx->irq);

	/* Request IRQ after all the harware initalization is finished */
	ret = devm_request_irq(bt_tx->dev, bt_tx->irq,
				ts_isr, IRQF_SHARED, TS_BT1120TX_NAME, bt_tx);
	if (ret) {
		dev_err(&pdev->dev, "Unable to request IRQ %d.\n", bt_tx->irq);
		goto reset_failed;
	}

	//init
	ret = bt1120_enc_init(&bt_tx->txCfg);
	if (ret)
		goto free_irq;

	return 0;

free_irq:
	devm_free_irq(&pdev->dev, bt_tx->irq, bt_tx);
reset_failed:
out_disable_clk:
	clk_disable_unprepare(bt_tx->clk);
io_unmap:
	devm_iounmap(&pdev->dev, bt_tx->reg_base);
	return ret;
}

/* initialize driver data structures */
static void ts_drv_init(struct ts_bt1120tx *bt_tx)
{
	/*
	 * the completion object will be used to notify
	 * the callee that the interrupt is done
	 */
	//init_completion(&bt_tx->complete);

	/*
	 * the spinlock will be used to synchronize the ISR with any
	 * element that might be access shared data (interrupt status)
	 */
	spin_lock_init(&bt_tx->irq_lock);
}

static int ts_bt1120tx_open(struct inode *inode, struct file *file)
{
	struct ts_bt1120tx *bt_tx = NULL;
	int ret = 0;

	//bt_tx = container_of(inode->i_cdev, struct ts_bt1120tx, misc_dev);
	if (g_bt_tx) {
		bt_tx = g_bt_tx;
	} else {
		bt_tx = kzalloc(sizeof(*bt_tx), GFP_KERNEL);
		if (!bt_tx) {
			//pr_err("bt1120tx open kzalloc is fail\n");
			ret = -ENOMEM;
			goto p_err;
		}
	}

	file->private_data = bt_tx;

	return 0;

p_err:
	return ret;
}

static int ts_bt1120tx_release(struct inode *inode, struct file *filp)
{
	if (g_bt_tx == NULL)
		kfree(filp->private_data);

	return 0;
}

static ssize_t ts_bt1120tx_read(struct file *file,
			char __user *buff, size_t count, loff_t *offp)
{
	return 0;
}

static ssize_t ts_bt1120tx_write(struct file *file,
			const char *buff, size_t count, loff_t *offp)
{
	return 0;
}

static int bt1120tx_bind_group(struct ts_bt1120tx *bt_tx, unsigned long arg)
{

	return 0;
}

static int bt1120tx_init(struct ts_bt1120tx *bt_tx, unsigned long arg)
{
	return 0;
}

#if 0
static int bt1120tx_req_buf(struct ts_bt1120tx *bt_tx, unsigned long arg)
{
	return 0;
}
#endif

static int bt1120tx_stream(struct ts_bt1120tx *bt_tx, unsigned long arg)
{
	return 0;
}

static int bt1120tx_qbuf(struct ts_bt1120tx *bt_tx, unsigned long arg)
{
	return 0;
}

static int bt1120tx_dqbuf(struct ts_bt1120tx *bt_tx, unsigned long arg)
{
	return 0;
}

static long ts_bt1120tx_ioctl(struct file *file,
					unsigned int cmd, unsigned long arg)
{
	int ret = 0;
	struct ts_bt1120tx *bt_tx;
	int reset;
	//int group;

	bt_tx = file->private_data;
	if (unlikely(bt_tx == NULL)) {
		pr_err("file bt_tx error.\n");
		return -EFAULT;
	}

	if (_IOC_TYPE(cmd) != BT1120TX_IOC_MAGIC)
		return -EFAULT;

	switch (cmd) {
	case BT1120TX_IOC_BIND_GROUP:
		ret = bt1120tx_bind_group(bt_tx, arg);
		if (ret)
			return ret;
		break;
	case BT1120TX_IOC_INIT:
		ret = bt1120tx_init(bt_tx, arg);
		if (ret)
			return -EFAULT;
		break;
	case BT1120TX_IOC_QBUF:
		ret = bt1120tx_qbuf(bt_tx, arg);
		if (ret)
			return ret;
		break;
	case BT1120TX_IOC_STREAM:
		ret = bt1120tx_stream(bt_tx, arg);
		if (ret)
			return ret;
		break;
	case BT1120TX_IOC_DQBUF:
		ret = bt1120tx_dqbuf(bt_tx, arg);
		if (ret)
			return ret;
		break;
	case BT1120TX_IOC_STATUS:
		break;
	case BT1120TX_IOC_GET_CFG:
		break;
	case BT1120TX_IOC_REST_HW:
		ret = get_user(reset, (int __user *)arg);
		if (unlikely(ret)) {
			pr_err("get reset data err.\n");
			return -EFAULT;
		}
		if (reset)
			bt1120_enc_reset(bt_tx->reg_base);

		break;
	default:
		pr_err("%s unknow ioctl cmd %x\n", __func__, cmd);
		ret = -EFAULT;
		break;
	}

	return 0;
}

static const struct file_operations bt1120tx_drv_fops = {
	.owner = THIS_MODULE,
	.open = ts_bt1120tx_open,
	.read = ts_bt1120tx_read,
	.write = ts_bt1120tx_write,
	.release = ts_bt1120tx_release,
	.unlocked_ioctl = ts_bt1120tx_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = ts_bt1120tx_ioctl,
#endif
};

static void ts_bt1120tx_interrupts_disable(struct ts_bt1120tx *bt_tx)
{
	unsigned long flags;

	spin_lock_irqsave(&bt_tx->irq_lock, flags);
	bt_tx->irq_mask = 0;
	bt1120Enc_EnaIntr_enable(bt_tx->irq_mask);
	spin_unlock_irqrestore(&bt_tx->irq_lock, flags);
}

static int ts_bt1120tx_probe(struct platform_device *pdev)
{
	int ret;
	struct ts_bt1120tx *bt_tx; //driver data
	int using_dac, consistent_using_dac;

	dev_dbg(&pdev->dev, "bt1120tx_probe\n");
	bt_tx = devm_kzalloc(&pdev->dev, sizeof(*bt_tx), GFP_KERNEL);
	if (!bt_tx)
		return -ENOMEM;

	g_bt_tx = bt_tx;
	ts_drv_init(bt_tx);

	bt1120tx_pre_config(bt_tx);
	ret = of_reserved_mem_device_init(&pdev->dev);
	if (ret)
		dev_info(&pdev->dev, "init reserved memory failed\n");
		/* continue to use dynamic allocation if failed */

	if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
		using_dac = 1;
		consistent_using_dac = 1;
	} else if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
		using_dac = 0;
		consistent_using_dac = 0;
	} else {
		dev_warn(&pdev->dev, "No suitable DMA available\n");
		//goto ignore_this_device;
	}

	bt_tx->txCfg.dma_size = bt_tx->txCfg.bank_num * 1920 * 1080 * 4;
	if (bt_tx->txCfg.dma_size > SZ_32M)
		bt_tx->txCfg.dma_size = SZ_32M;

	bt_tx->txCfg.dma_vaddr = dma_alloc_coherent(&pdev->dev,
			 bt_tx->txCfg.dma_size,
			  &bt_tx->txCfg.dma_handler, GFP_KERNEL);

	dev_dbg(&pdev->dev, "dma alloc 0x%llx to %p!\n",
		bt_tx->txCfg.dma_handler, bt_tx->txCfg.dma_vaddr);

	/*
	 * we allocate the misc device structure as part of our own allocation,
	 * so we can get a pointer to our priv structure later on with
	 * container_of(). This isn't really necessary as we have a fixed minor
	 * number anyway, but this is to avoid statics.
	 */
#if defined(TS_BT1120TX_MINOR)
	bt_tx->misc_dev.minor	= TS_BT1120TX_MINOR,
#else
	bt_tx->misc_dev.minor	= TS_BT1120TX_MISCDEV_MINOR,
#endif
	bt_tx->misc_dev.name	= TS_BT1120TX_NAME,
	bt_tx->misc_dev.fops	= &bt1120tx_drv_fops;

	/* register misc device */
	ret = misc_register(&bt_tx->misc_dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "misc_register() for minor %d failed\n",
			TS_BT1120TX_MISCDEV_MINOR);
		goto err_misc_deregister;
	}

	ret = ts_bt1120tx_parse_dt(pdev, bt_tx);
	if (ret)
		goto free_dma;

	//complete(&bt_tx->complete);
	platform_set_drvdata(pdev, bt_tx);
	dev_info(&pdev->dev, "ts bt1120tx initialized.\n");

	ts_bt1120tx_change_bank(bt_tx); //test...
	//wait_for_completion_timeout(&bt_tx->complete, msecs_to_jiffies(200));

	return 0;

err_misc_deregister:
	misc_deregister(&bt_tx->misc_dev);
free_dma:
	dma_free_coherent(&pdev->dev, bt_tx->txCfg.dma_size,
		 bt_tx->txCfg.dma_vaddr, bt_tx->txCfg.dma_handler);
	devm_kfree(&pdev->dev, bt_tx);

	return ret;
}

static int ts_bt1120tx_remove(struct platform_device *pdev)
{
	struct ts_bt1120tx *bt_tx = platform_get_drvdata(pdev);

	/* shutdown irq */
	ts_bt1120tx_interrupts_disable(bt_tx);

	misc_deregister(&bt_tx->misc_dev);
	clk_disable_unprepare(bt_tx->clk);
	devm_free_irq(&pdev->dev, bt_tx->irq, bt_tx);
	dma_free_coherent(&pdev->dev, bt_tx->txCfg.dma_size,
		 bt_tx->txCfg.dma_vaddr, bt_tx->txCfg.dma_handler);
	devm_iounmap(&pdev->dev, bt_tx->reg_base);
	//release_mem_region(resource_start(&pdev->dev, 0),
			//	resource_len(&pdev->dev, 0));
	devm_kfree(&pdev->dev, bt_tx);
	return 0;
}

static int ts_bt1120tx_suspend(struct platform_device *pdev,
				pm_message_t state)
{
	return 0;
}

static int ts_bt1120tx_resume(struct platform_device *pdev)
{
	return 0;
}

static void ts_bt1120tx_shutdown(struct platform_device *pdev)
{
	//return;
}

#if defined(CONFIG_OF) || 1
static const struct of_device_id ts_bt1120tx_of_match[] = {
	{.compatible = "ts,bt1120tx",
	 .data = &ts_bt1120tx_data,
	},

	{}
};
MODULE_DEVICE_TABLE(of, ts_bt1120tx_of_match);
#endif

static struct platform_driver ts_bt1120tx_driver = {
	.driver = {
		.name = "ts-bt1120tx",
		.of_match_table = of_match_ptr(ts_bt1120tx_of_match),
	},
	.probe = ts_bt1120tx_probe,
	.remove = ts_bt1120tx_remove,
	.suspend = ts_bt1120tx_suspend,
	.resume = ts_bt1120tx_resume,
	.shutdown = ts_bt1120tx_shutdown,
};

#if 0
static int __init ts_bt1120tx_init(void)
{
	return platform_dirver_register(&ts_bt1120tx_driver);
}

//arch_initcall(ts_bt1120tx_init);

static int __exit ts_bt1120tx_exit(void)
{
	return platform_driver_unregister(&ts_bt1120tx_driver);
}
#endif
/* register platform driver to platform bus */
module_platform_driver(ts_bt1120tx_driver);

MODULE_DESCRIPTION("TS BT1120TX driver");
MODULE_AUTHOR("Json Liu, <liuluyang530@126.com>");
MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338525.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IsaacSim Asserts 配置

IsaacSim Asserts 配置 背景解决方案资源准备具体操作步骤验证 背景 我是习惯使用 isaacsim 的 standalone 模式&#xff0c;使用 python 脚本直接运行 script&#xff0c;然后弹窗&#xff0c;按照规则正确运行即可&#xff0c;但是&#xff0c;这就导致了一些问题出现&#…

接口自动化 ——fixture allure

一.参数化实现数据驱动 上一篇介绍了参数化&#xff0c;这篇 说说用参数化实现数据驱动。在有很多测试用例的时候&#xff0c;可以将测试用例都存储在文件里&#xff0c;进行读写调用。本篇主要介绍 csv 文件和 json 文件。 1.读取 csv 文件数据 首先创建 csv 文件&#xff…

systemctl管理指令

今天我们来继续学习服务管理指令,接下来才是重头戏-systemctl,那么话不多说,直接开始吧. systemctl管理指令 1.基本语法: systemctl [start | stop | restart | status]服务 注&#xff1a;systemctl指令管理的服务在/usr/lib/ systemd/system查看 2.systemctl设置服务的自…

【文件操作与IO】详细解析文件操作与IO (二)

本篇博客是上一篇文章的续写,重点介绍数据流,还包括三道练习题. &#x1f40e;文章专栏: JavaEE初阶 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&#x1f680; 要开心…

go-map+sync.map的底层原理

map 哈希冲突解决方式 1.拉链法 2.开放地址法 底层结构 Go 的 map 在源码中由 runtime.hmap 结构体表示&#xff0c;buckets-指向桶数组的指针(常规桶)&#xff0c;oldbuckets-扩容时指向旧桶数组的指针。 type hmap struct {count int // 当前元素个数&#xff08;len…

Day53 二叉树的层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* T…

物联网智慧教室项目(完整版)

物联网智慧教室项目(一)&#xff1a;智慧教室项目解决方案 一、智慧教室项目设计 &#xff08;一&#xff09;环境信息采集控制功能 1、硬件设计 使用STM32开发板模拟灯光控制&#xff0c;报警控制&#xff0c;光照信息采集&#xff1a; 灯光控制通过GPIO控制板载LED报警控…

计算机网络期中复习笔记(自用)

复习大纲 –第一章 概述 计算机网络的组成 网络边缘&#xff1a;主机和网络应用程序&#xff08;又称为“端系统”&#xff09; 端系统中运行的程序之间的通信方式可划分为两大类&#xff1a; 客户/服务器方式&#xff08;C/S方式&#xff09; 对等方式&#xff08;P2P方式…

14.Chromium指纹浏览器开发教程之WebGL指纹定制

WebGL指纹概述 当在浏览器打开的网页上浏览内容时&#xff0c;看到的大多是平面的、静态的图像和文字。但是有时想要在网页上看到更加生动、立体的图像&#xff0c;如3D游戏、虚拟现实应用等。这时&#xff0c;就需要用到WebGL。 简单来说&#xff0c;WebGL&#xff08;Web G…

GitHub SSH连接终极解决方案

GitHub SSH连接终极解决方案&#xff1a;443端口修改多场景故障排查指南 一、问题现象速查 当开发者执行以下命令时出现连接异常&#xff1a; ssh -T gitgithub.com常见报错类型&#xff1a; 经典端口阻塞ssh: connect to host github.com port 22: Connection refused密钥验…

每日算法【双指针算法】(Day 1-移动零)

双指针算法 1.算法题目&#xff08;移动零&#xff09;2.讲解算法原理3.编写代码 1.算法题目&#xff08;移动零&#xff09; 2.讲解算法原理 数组划分&#xff0c;数组分块&#xff08;快排里面最核心的一步&#xff09;只需把0改为tmp 双指针算法&#xff1a;利用数组下标来…

B端管理系统:企业运营的智慧大脑,精准指挥

B端管理系统的定义与核心功能 B端管理系统&#xff08;Business Management System&#xff09;是专门设计用于支持企业内部运作和外部业务交互的一套软件工具。它集成了多种功能模块&#xff0c;包括但不限于客户关系管理(CRM)、供应链管理(SCM)、人力资源管理(HRM)以及财务管…

使用Java基于Geotools的SLD文件编程式创建与磁盘生成实战

前言 在地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;地图的可视化呈现至关重要&#xff0c;而样式定义语言&#xff08;SLD&#xff09;文件为地图元素的样式配置提供了强大的支持。SLD 能够精确地定义地图图层中各类要素&#xff08;如点、线、面、文本等&#x…

Git 命令速查手册

听说用美图可以钓读者&#xff1f; 一、基础操作核心命令 1. 仓库初始化与克隆 命令作用示例git init创建新仓库git init my-projectgit clone克隆远程仓库git clone [https://github.com/user/repo.git](https://github.com/user/repo.git)git remote add关联远程仓库git re…

网络编程 - 4 ( TCP )

目录 TCP 流套接字编程 API 介绍 SeverSocket Socket 用 TCP 实现一个回显服务器 服务端 客户端 运行调试 第一个问题&#xff1a;PrintWriter 内置的缓冲区 - flush 刷新解决 第二个问题&#xff1a;上述代码中&#xff0c;需要进行 close 操作吗&#xff1f; 第三…

OSPF综合实验(HCIP)

1&#xff0c;R5为ISP&#xff0c;其上只能配置Ip地址&#xff1b;R4作为企业边界路由器&#xff0c; 出口公网地址需要通过ppp协议获取&#xff0c;并进行chap认证 2&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 3&#xff0c;所有设备均可访问R5的环回&…

真实波幅策略思路

该策略是一种基于ATR&#xff08;Average True Range&#xff09;指标的交易策略&#xff0c;主要用于期货市场中的日内交易。策略的核心思想是利用ATR指标来识别市场的波动范围&#xff0c;并结合均线过滤来确定买入和卖出的时机。 交易逻辑思维 1. 数据准备与初始化 - 集合竞…

leetcode 674. Longest Continuous Increasing Subsequence

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析明确并理解递推公式 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。与第300题的唯一区别就是&#…

STM32 外部中断EXTI

目录 外部中断基础知识 STM32外部中断框架 STM32外部中断机制框架 复用功能 重映射 中断嵌套控制器NVIC 外部中断按键控制LED灯 外部中断基础知识 STM32外部中断框架 中断的概念&#xff1a;在主程序运行过程中&#xff0c;出现了特点的中断触发条件&#xff0c;使得…

Linux:基础IO---动静态库

文章目录 1. 动静态库前置知识1.1 动静态库知识回顾1.2 什么是动静态库 2. 动静态库2.1 站在库的制作者的角度2.2 站在库的使用者的角度2.3 动态库是怎么被加载的&#xff08;原理&#xff09; 序&#xff1a;上一篇文章我们从认识到理解&#xff0c;从理解到实现场景&#xff…