前些年做视频输出项目的时候用过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");