- 9b31d0, [fix](sample):fix some error in sample_vio. - d097e0, [style](gdc):Modify dwa to ldc. - 6cc776, [fix](audio):fix the bug in sample_audio case4 when open vqe. Change-Id: Id429708a0aa8b74ce1e1094838c62b6e8caf112d
2712 lines
77 KiB
C
2712 lines
77 KiB
C
#include "lt9611.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c-dev.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include "cvi_sys.h"
|
|
#include <getopt.h>
|
|
|
|
#include "sample_comm.h"
|
|
|
|
#define LT9611_I2C_NAME "lt9611"
|
|
#define LT9611_I2C_ADDR 0x3B /* 7bit addr */
|
|
#define LT9611_I2C_DEV 4
|
|
|
|
void Timer0_Delay1ms(uint32_t u32CNT)
|
|
{
|
|
usleep(u32CNT*1000);
|
|
}
|
|
|
|
/******************************** debug *******************/
|
|
#define _pcr_mk_printf_
|
|
#define _mipi_Dphy_debug_
|
|
#define _htotal_stable_check_
|
|
|
|
/* pattern */
|
|
//#define _pattern_test_
|
|
|
|
//#define cec_on
|
|
|
|
#define _enable_read_edid_
|
|
/***********************************************************/
|
|
#define single_port_mipi 1
|
|
#define dual_port_mipi 2
|
|
|
|
//Do not support 3lane
|
|
#define lane_cnt_1 1
|
|
#define lane_cnt_2 2
|
|
#define lane_cnt_4 0
|
|
|
|
#define audio_i2s 0
|
|
#define audio_spdif 1
|
|
|
|
#define dsi 0
|
|
#define csi 1
|
|
|
|
#define Non_Burst_Mode_with_Sync_Events 0x00
|
|
#define Non_Burst_Mode_with_Sync_Pulses 0x01
|
|
#define Burst_Mode 0x02
|
|
|
|
#define ac_mode 0
|
|
#define dc_mode 1
|
|
|
|
#define hdcp_disable 0
|
|
#define hdcp_enable 1
|
|
|
|
#define HPD_INTERRUPT_ENABLE 0x01
|
|
#define VID_CHG_INTERRUPT_ENABLE 0x02
|
|
#define CEC_INTERRUPT_ENABLE 0x03
|
|
|
|
#define RGB888 0x00
|
|
#define YUV422 0x01
|
|
|
|
#define DVI 0x00
|
|
#define HDMI 0x01
|
|
|
|
#define AR_ND 0x00
|
|
#define AR_4_3 0x01
|
|
#define AR_16_9 0x02
|
|
|
|
|
|
#define MPEG_PKT_EN 0x01
|
|
#define AIF_PKT_EN 0x02
|
|
#define SPD_PKT_EN 0x04
|
|
#define AVI_PKT_EN 0x08
|
|
#define UD1_PKT_EN 0x10
|
|
#define UD0_PKT_EN 0x20
|
|
|
|
#define CEC_SEND_DONE 0x01
|
|
#define CEC_REC_DATA 0x02
|
|
#define CEC_NACK 0x04
|
|
#define CEC_ARB_LOST 0x08
|
|
#define CEC_ERROR_INITIATOR 0x10
|
|
#define CEC_ERROR_FOLLOWER 0x20
|
|
#define CEC_WAKE_UP 0x40
|
|
|
|
|
|
#define MSG_USRCNTRL_PRESS 0X44
|
|
#define MSG_USRCNTRL_RELEASE 0X45
|
|
#define MSG_OSD_GET 0x46
|
|
#define MSG_OSD_SET 0x47
|
|
#define MSG_PHYADDR_GET 0x83
|
|
#define MSG_PHYADDR_SET 0x84
|
|
#define MSG_STREAM_SET 0X86
|
|
#define MSG_ACTIVESOURCE_GET 0X82
|
|
#define MSG_VENDOR_GET 0x8C
|
|
#define MSG_MENUSTATUS_GET 0X8D
|
|
#define MSG_MENUSTATUS_SET 0X8E
|
|
#define MSG_MEBUSTATUS_ACTIVE 0X00
|
|
#define MSG_POWERSTATUS_GET 0X8F
|
|
#define MSG_POWERSTATUS_SET 0X90
|
|
#define MSG_POWERSTATUS_ON 0X00
|
|
#define MSG_CECVERSION_GET 0x9F
|
|
#define MSG_CECVERSION_SET 0X9E
|
|
#define MSG_CECVERSION_1_4 0X05
|
|
#define MSG_FEATURE_ABRT 0x00
|
|
#define MSG_ABORT 0xFF
|
|
#define MSG_ABRT_REASON 0x00
|
|
|
|
|
|
#define CEC_ABORT_REASON_0 0x00 //Unrecoanized opcode
|
|
#define CEC_ABORT_REASON_1 0x01 //Not in correct mode to respond
|
|
#define CEC_ABORT_REASON_2 0x02 //Cannot provide source
|
|
#define CEC_ABORT_REASON_3 0x03 //Invalid operand
|
|
#define CEC_ABORT_REASON_4 0x04 //Refused
|
|
#define CEC_ABORT_REASON_5 0x05 //Unable to determine
|
|
|
|
typedef struct Lontium_IC_Mode{
|
|
CVI_U8 mipi_port_cnt; //1 or 2
|
|
CVI_U8 mipi_lane_cnt; //1 or 2 or 4
|
|
bool mipi_mode; //dsi or csi
|
|
CVI_U8 video_mode; //Non-Burst Mode with Sync Pulses; Non-Burst Mode with Sync Events
|
|
bool audio_out; //i2s or spdif
|
|
bool hdmi_coupling_mode;//ac_mode or dc_mode
|
|
bool hdcp_encryption; //hdcp_enable or hdcp_diable
|
|
bool hdmi_mode;
|
|
CVI_U8 input_color_space; //RGB888 or YUV422
|
|
} __Lontium_IC_Mode;
|
|
|
|
|
|
typedef struct video_timing{
|
|
CVI_U16 hfp;
|
|
CVI_U16 hs;
|
|
CVI_U16 hbp;
|
|
CVI_U16 hact;
|
|
CVI_U16 htotal;
|
|
CVI_U16 vfp;
|
|
CVI_U16 vs;
|
|
CVI_U16 vbp;
|
|
CVI_U16 vact;
|
|
CVI_U16 vtotal;
|
|
bool h_polarity;
|
|
bool v_polarity;
|
|
CVI_U16 vic;
|
|
CVI_U8 aspact_ratio; // 0=no data, 1=4:3, 2=16:9, 3=no data.
|
|
CVI_U32 pclk_khz;
|
|
} __video_timing;
|
|
|
|
typedef struct cec_msg{
|
|
CVI_U8 cec_status;
|
|
CVI_U8 rx_data_buff[16];
|
|
CVI_U8 tx_data_buff[18];
|
|
CVI_U8 logical_address;
|
|
CVI_U16 physical_address;
|
|
CVI_U8 destintion;
|
|
CVI_U8 retries_times;
|
|
bool la_allocation_done;
|
|
bool report_physical_address_done;
|
|
} __cec_msg;
|
|
|
|
typedef enum VideoFormat
|
|
{
|
|
video_640x480_60Hz_vic1 = 1, //vic 1
|
|
video_720x480_60Hz_vic3, //vic 2
|
|
video_720x576_50Hz_vic,
|
|
video_1280x720_60Hz_vic4, //vic 3
|
|
video_1920x1080_60Hz_vic16, //vic 4
|
|
|
|
video_1920x1080i_60Hz_169, //vic 5
|
|
video_720x480i_60Hz_43, //vic 6
|
|
video_720x480i_60Hz_169, //vic 7
|
|
video_720x240P_60Hz_43, //vic 8
|
|
video_720x240P_60Hz_169, //vic 9
|
|
|
|
video_1280x720_50Hz_vic,
|
|
video_1280x720_30Hz_vic,
|
|
|
|
video_3840x2160_30Hz_vic,
|
|
video_3840x2160_25Hz_vic,
|
|
video_3840x2160_24Hz_vic,
|
|
|
|
video_3840x1080_60Hz_vic,
|
|
video_1024x600_60Hz_vic,
|
|
video_1080x1920_60Hz_vic,
|
|
video_720x1280_60Hz_vic,
|
|
video_1280x800_60Hz_vic,
|
|
video_540x960_60Hz_vic,
|
|
video_1366x768_60Hz_vic,
|
|
|
|
video_2560x1600_60Hz_vic,
|
|
video_2560x1440_60Hz_vic,
|
|
video_2560x1080_60Hz_vic,
|
|
|
|
video_1920x1080_50Hz_vic,
|
|
video_1920x1080_30Hz_vic,
|
|
video_1920x1080_25Hz_vic,
|
|
video_1920x1080_24Hz_vic,
|
|
|
|
video_2560x720_60Hz_vic,
|
|
|
|
video_other,
|
|
video_none
|
|
}__VideoFormat;
|
|
|
|
typedef enum
|
|
{
|
|
I2S_2CH,
|
|
I2S_8CH,
|
|
SPDIF
|
|
} _Audio_Input_Mode;
|
|
|
|
#define Audio_Input_Mode I2S_2CH
|
|
|
|
typedef enum
|
|
{
|
|
Input_RGB888,
|
|
Input_RGB565,
|
|
Input_YCbCr444,
|
|
Input_YCbCr422_16BIT,
|
|
Input_YCbCr422_20BIT,
|
|
Input_YCbCr422_24BIT,
|
|
Input_BT1120_16BIT,
|
|
Input_BT1120_20BIT,
|
|
Input_BT1120_24BIT,
|
|
Input_BT656_8BIT,
|
|
Input_BT656_10BIT,
|
|
Input_BT656_12BIT
|
|
} _Video_Input_Mode;
|
|
|
|
#define Video_Input_Mode Input_RGB888
|
|
|
|
typedef enum
|
|
{
|
|
Output_RGB888,
|
|
Output_YCbCr444,
|
|
Output_YCbCr422_16BIT,
|
|
Output_YCbCr422_20BIT,
|
|
Output_YCbCr422_24BIT
|
|
} _Video_Output_Mode;
|
|
|
|
#define Video_Output_Mode Output_RGB888
|
|
|
|
struct Lontium_IC_Mode lt9611 = {
|
|
single_port_mipi, //mipi_port_cnt; //single_port_mipi or dual_port_mipi
|
|
lane_cnt_4, //mipi_lane_cnt; //1 or 2 or 4
|
|
dsi, //mipi_mode; //dsi or csi
|
|
Burst_Mode,
|
|
audio_i2s, //audio_out //audio_i2s or audio_spdif //hdmi_coupling_mode;//ac_mode or dc_mode
|
|
dc_mode, //hdmi_coupling_mode;//ac_mode or dc_mode
|
|
hdcp_disable, //hdcp_encryption //hdcp_enable or hdcp_disable
|
|
HDMI, //HDMI or DVI
|
|
RGB888 //RGB888 or YUV422
|
|
};
|
|
|
|
#define MAX_CMD_OPTIONS 128
|
|
typedef enum _ARG_TYPE_ {
|
|
ARG_INT = 0,
|
|
ARG_UINT,
|
|
ARG_STRING,
|
|
} ARG_TYPE;
|
|
|
|
typedef struct _optionExt_ {
|
|
struct option opt;
|
|
int type;
|
|
int64_t min;
|
|
int64_t max;
|
|
const char *help;
|
|
} optionExt;
|
|
|
|
static optionExt long_option_ext[] = {
|
|
{{"resolution", optional_argument, NULL, 'r'}, ARG_STRING, 0, 0,
|
|
"select hdmi display solution"},
|
|
{{"help", no_argument, NULL, 'h'}, ARG_STRING, 0, 0,
|
|
"print usage."},
|
|
{{NULL, 0, NULL, 0}, ARG_INT, 0, 0, "no param: just init the hdmi."}
|
|
};
|
|
|
|
static const char* s_hdmi_resolution_arr[] = {
|
|
"1024x768_60HZ",
|
|
"1280x720_60HZ",
|
|
"1280x1024_60HZ",
|
|
"1600x1200_60HZ",
|
|
"1920x1080_30HZ",
|
|
"1920x1080_60HZ",
|
|
};
|
|
|
|
static LT9611_VIDEO_FORMAT_E g_video_format = E_LT9611_VIDEO_1920x1080_60HZ;
|
|
//DTV // hfp, hs, hbp,hact,htotal,vfp, vs, vbp,vact,vtotal, hfp, hs, hbp,hact,htotal,vfp, vs, vbp,vact,vtotal, h_polary, v_polary, vic, pclk_khz
|
|
static struct video_timing video_640x480_60Hz ={16, 96, 48, 640, 800, 10, 2, 33, 480, 525, 0, 0, 1, AR_4_3, 25000};
|
|
static struct video_timing video_720x480_60Hz ={16, 62, 60, 720, 858, 9, 6, 30, 480, 525, 0, 0, 2, AR_4_3, 27000};
|
|
static struct video_timing video_720x576_50Hz ={12, 64, 68, 720, 864, 5, 5, 39, 576, 625, 0, 0, 17,AR_4_3, 27000};
|
|
|
|
static struct video_timing video_1280x720_60Hz ={110,40, 220,1280, 1650, 5, 5, 20, 720, 750, 1, 1, 4, AR_16_9,74250};
|
|
static struct video_timing video_1280x720_50Hz ={440,40, 220,1280, 1980, 5, 5, 20, 720, 750, 1, 1, 19,AR_16_9,74250};
|
|
static struct video_timing video_1280x720_30Hz ={1760, 40, 220,1280, 3300, 5, 5, 20, 720, 750, 1,1,0, AR_16_9,74250};
|
|
|
|
static struct video_timing video_1920x1080_60Hz ={88, 44, 148,1920, 2200, 4, 5, 36, 1080, 1125, 1,1,16,AR_16_9,148500};
|
|
static struct video_timing video_1920x1080_50Hz ={528, 44, 148,1920, 2640, 4, 5, 36, 1080, 1125, 1,1,31,AR_16_9,148500};
|
|
static struct video_timing video_1920x1080_30Hz ={88, 44, 148,1920, 2200, 4, 5, 36, 1080, 1125, 1,1,34,AR_16_9,74250};
|
|
static struct video_timing video_1920x1080_25Hz ={528, 44, 148,1920, 2640, 4, 5, 36, 1080, 1125, 1,1,33,AR_16_9,74250};
|
|
static struct video_timing video_1920x1080_24Hz ={638, 44, 148,1920, 2750, 4, 5, 36, 1080, 1125, 1,1,32,AR_16_9,74250};
|
|
|
|
static struct video_timing video_3840x2160_30Hz ={176,88, 296,3840, 4400, 8, 10, 72, 2160, 2250, 1,1,95,AR_16_9, 297000};
|
|
static struct video_timing video_3840x2160_25Hz ={1056,88, 296,3840, 5280, 8, 10, 72, 2160, 2250,1,1,94,AR_16_9, 297000};
|
|
static struct video_timing video_3840x2160_24Hz ={1276,88, 296,3840, 5500, 8, 10, 72, 2160, 2250,1,1,93,AR_16_9,297000};
|
|
|
|
static struct video_timing video_1024x768_60Hz ={24, 136, 160, 1024, 1344, 3, 6, 29, 768, 806, 0,0,0,AR_16_9,65000};
|
|
static struct video_timing video_1280x1024_60Hz ={48, 112, 248, 1280, 1688, 1, 3, 38, 1024, 1066, 1,1,0,AR_16_9,108000};
|
|
static struct video_timing video_1600x1200_60Hz ={64, 192, 304, 1600, 2160, 1, 3, 46, 1200, 1250, 1,1,0,AR_16_9,162000};
|
|
|
|
static struct video_timing video_1280x800_60Hz ={28, 32, 100, 1280, 1440, 2, 6, 15, 800, 823, 0,0,0,AR_16_9,71000};
|
|
|
|
/*
|
|
code struct video_timing video_2560x1080_60Hz ={248,44, 148,2560,2720, 4, 5, 11, 1080,1100, 1,1,0,AR_16_9,198000};
|
|
|
|
//VESA-DMT
|
|
code struct video_timing video_800x600_60Hz ={48, 128, 88, 800, 1056, 1, 4, 23, 600, 628, 1,1,0,AR_16_9,40000};
|
|
code struct video_timing video_1024x768_60Hz ={24, 136, 160, 1024, 1344, 3, 6, 29, 768, 806, 0,0,0,AR_16_9,65000};
|
|
//code struct video_timing video_1280x768_60Hz ={48, 32, 80, 1280, 1440, 3, 7, 12, 768, 790, 1,0,0,AR_16_9,68250}; //reduced blank
|
|
code struct video_timing video_1280x768_60Hz ={64, 128, 192, 1280, 1664, 3, 7, 20, 768, 798, 0,1,0,AR_16_9,79500}; //Normal
|
|
|
|
//20190328
|
|
//code struct video_timing video_1280x800_60Hz ={72, 128, 200, 1280, 1680, 3, 6, 22, 800, 831, 0,1,0,AR_16_9,83500};
|
|
code struct video_timing video_1280x800_60Hz ={28, 32, 100, 1280, 1440, 2, 6, 15, 800, 823, 0,0,0,AR_16_9,71000};
|
|
code struct video_timing video_1280x960_60Hz ={96, 112, 312, 1280, 1800, 1, 3, 36, 960, 1000, 1,1,0,AR_16_9,108000};
|
|
|
|
code struct video_timing video_1280x800_30Hz ={72, 128, 200, 1280, 1680, 3, 6, 22, 800, 831, 0,1,0,AR_16_9,41750};
|
|
code struct video_timing video_1280x960_30Hz ={96, 112, 312, 1280, 1800, 1, 3, 36, 960, 1000, 1,1,0,AR_16_9,54000};
|
|
|
|
code struct video_timing video_1280x1024_60Hz ={48, 112, 248, 1280, 1688, 1, 3, 38, 1024, 1066, 1,1,0,AR_16_9,108000};
|
|
code struct video_timing video_1600x1200_60Hz ={64, 192, 304, 1600, 2160, 1, 3, 46, 1200, 1250, 1,1,0,AR_16_9,162000};
|
|
//code struct video_timing video_1680x1050_60Hz ={48, 32, 80, 1680, 1840, 3, 6, 21, 1050, 1080, 1,0,0,AR_16_9,119000}; //reduced blank
|
|
code struct video_timing video_1680x1050_60Hz ={104, 176, 280, 1680, 2240, 3, 6, 30, 1050, 1089, 0,1,0,AR_16_9,146250};//Normal
|
|
|
|
code struct video_timing video_1280x720_30Hz ={1760, 40, 220,1280, 3300, 5, 5, 20, 720, 750, 1,1,0, AR_16_9,74250};
|
|
code struct video_timing video_1024x600_60Hz ={60,60, 100,1024, 1154, 2, 5, 10, 600, 617, 1,1,0,AR_16_9,34000};
|
|
|
|
code struct video_timing video_1366x768_60Hz ={14, 56, 64,1366, 1500, 1, 3, 28, 768, 800, 1,1,0, AR_16_9,74000};
|
|
|
|
code struct video_timing video_2560x1440_50Hz ={176,272, 448,2560, 3456, 3, 5, 36, 1440, 1484, 1,1,0, AR_16_9,256250};
|
|
code struct video_timing video_2560x1440_60Hz ={48,32, 80,2560, 2720, 3, 5, 33, 1440, 1481, 1,1,0, AR_16_9,241500};
|
|
|
|
//20180731 //hfp, hs, hbp,hact,htotal,vfp, vs, vbp,vact,vtotal, pclk_khz
|
|
code struct video_timing video_2560x1600_60Hz ={48,32, 80,2560, 2720, 3, 6, 37, 1600, 1646, 1,1,0,AR_16_9,268500};
|
|
|
|
//VR timing
|
|
code struct video_timing video_3840x1080_60Hz ={176,88, 296,3840, 4400, 4, 5, 36, 1080, 1125, 1,1,0, AR_16_9,297000};
|
|
code struct video_timing video_2560x720_60Hz ={220,80, 440,2560, 3300, 5, 5, 20, 720, 750, 1, 1, 0, AR_16_9,148500};
|
|
|
|
//mipi panel resolution
|
|
code struct video_timing video_1080x1920_60Hz ={ 4, 5, 36, 1080, 1125, 88, 44, 148,1920, 2200, 1,1,0,AR_16_9,148500};
|
|
code struct video_timing video_720x1280_60Hz ={ 5, 5, 20, 720, 750, 110,40, 220,1280, 1650, 1,1,0,AR_16_9,74250};
|
|
code struct video_timing video_540x960_60Hz ={30, 10, 30, 540, 610, 10, 10, 10, 960, 990, 1,1,0,AR_16_9,33500};
|
|
*/
|
|
|
|
//others
|
|
static struct video_timing video_1200x1920_60Hz ={180,60, 160, 1200, 1600, 35, 10, 25, 1920, 1990, 1, 1, 0, AR_16_9,191040};
|
|
static struct video_timing video_1920x720_60Hz ={88, 44, 148, 1920, 2200, 5, 5, 20, 720, 750, 1, 1, 0, AR_16_9,100000};
|
|
|
|
|
|
struct video_timing *video;
|
|
struct cec_msg lt9611_cec_msg = {0};
|
|
|
|
//static CVI_U8 CEC_RxData_Buff[16];
|
|
static CVI_U8 CEC_TxData_Buff[18];
|
|
|
|
CVI_U8 pcr_m;
|
|
bool flag_cec_data_received = 0;
|
|
|
|
CVI_U8 Sink_EDID[256];
|
|
bool Tx_HPD=0;
|
|
|
|
enum VideoFormat Video_Format;
|
|
static int lt9611_i2c_write_byte(CVI_U8 u8RegAddr, CVI_U8 u8Data);
|
|
static int lt9611_i2c_read_byte(CVI_U8 u8RegAddr);
|
|
static int fd = -1;
|
|
|
|
void LT9611_init_i2c(void)
|
|
{
|
|
char temp[16] = {0};
|
|
|
|
snprintf(temp, sizeof(temp), "/dev/i2c-%u", LT9611_I2C_DEV);
|
|
|
|
fd = open(temp, O_RDWR);
|
|
|
|
if(fd < 0)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_ERR, "open %s error!!!", temp);
|
|
}
|
|
}
|
|
|
|
static int lt9611_i2c_write_byte(CVI_U8 u8RegAddr, CVI_U8 u8Data)
|
|
{
|
|
uint8_t temp[2] = {0};
|
|
|
|
struct i2c_rdwr_ioctl_data data;
|
|
struct i2c_msg msg;
|
|
|
|
data.msgs = &msg;
|
|
|
|
temp[0] = u8RegAddr;
|
|
temp[1] = u8Data;
|
|
|
|
data.msgs[0].addr = LT9611_I2C_ADDR;
|
|
data.msgs[0].flags = 0;
|
|
data.msgs[0].len = 2;
|
|
data.msgs[0].buf = temp;
|
|
|
|
data.nmsgs = 1;
|
|
|
|
int ret = ioctl(fd, I2C_RDWR, (unsigned long) &data);
|
|
|
|
if(ret < 0)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_ERR, "lt9611_i2c_write_byte, addr: %x error!!!", u8RegAddr);
|
|
return CVI_FAILURE;
|
|
}
|
|
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
static int lt9611_i2c_read_byte(CVI_U8 u8RegAddr)
|
|
{
|
|
struct i2c_rdwr_ioctl_data data;
|
|
struct i2c_msg msg[2];
|
|
|
|
uint8_t result = 0x00;
|
|
|
|
data.msgs = &msg[0];
|
|
|
|
data.msgs[0].addr = LT9611_I2C_ADDR;
|
|
data.msgs[0].flags = 0;
|
|
data.msgs[0].len = 1;
|
|
data.msgs[0].buf = &u8RegAddr;
|
|
|
|
data.msgs[1].addr = LT9611_I2C_ADDR;
|
|
data.msgs[1].flags = I2C_M_RD;
|
|
data.msgs[1].len = 1;
|
|
data.msgs[1].buf = &result;
|
|
|
|
data.nmsgs = 2;
|
|
|
|
int ret = ioctl(fd, I2C_RDWR, (unsigned long) &data);
|
|
|
|
if(ret < 0)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_ERR, "lt9611_i2c_read_byte, addr: %x error!!!", u8RegAddr);
|
|
return -1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void LT9611_Chip_ID(void)
|
|
{
|
|
lt9611_i2c_write_byte(0xFF,0x80);
|
|
lt9611_i2c_write_byte(0xee,0x01);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611 ring Chip ID = 0x%x, 0x%x, 0x%x\n",lt9611_i2c_read_byte(0x00),
|
|
lt9611_i2c_read_byte(0x01), lt9611_i2c_read_byte(0x02));
|
|
lt9611_i2c_write_byte(0xFF,0x81);
|
|
lt9611_i2c_write_byte(0x01,0x18); //sel xtal clock
|
|
lt9611_i2c_write_byte(0xFF,0x80);
|
|
}
|
|
|
|
void LT9611_RST_PD_Init(void)
|
|
{
|
|
/* power consumption for standby */
|
|
lt9611_i2c_write_byte(0xFF,0x81);
|
|
lt9611_i2c_write_byte(0x02,0x48);
|
|
lt9611_i2c_write_byte(0x23,0x80);
|
|
lt9611_i2c_write_byte(0x30,0x00);
|
|
lt9611_i2c_write_byte(0x01,0x00); /* i2c stop work */
|
|
}
|
|
|
|
void LT9611_LowPower_mode(bool on)
|
|
{
|
|
/* only hpd irq is working for low power consumption */
|
|
/* 1.8V: 15 mA */
|
|
if(on)
|
|
{
|
|
lt9611_i2c_write_byte(0xFF,0x81);
|
|
lt9611_i2c_write_byte(0x02,0x49);
|
|
lt9611_i2c_write_byte(0x23,0x80);
|
|
lt9611_i2c_write_byte(0x30,0x00); //0x00 --> 0xc0, tx phy and clk can not power down, otherwise dc det don't work.
|
|
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x11,0x0a);
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xFF,0x81);
|
|
lt9611_i2c_write_byte(0x02,0x12);
|
|
lt9611_i2c_write_byte(0x23,0x40);
|
|
lt9611_i2c_write_byte(0x30,0xea);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x11,0xfa);
|
|
}
|
|
}
|
|
|
|
void LT9611_System_Init(void) //dsren
|
|
{
|
|
lt9611_i2c_write_byte(0xFF,0x82);
|
|
lt9611_i2c_write_byte(0x51,0x11);
|
|
//Timer for Frequency meter
|
|
lt9611_i2c_write_byte(0xFF,0x82);
|
|
lt9611_i2c_write_byte(0x1b,0x69); //Timer 2
|
|
lt9611_i2c_write_byte(0x1c,0x78);
|
|
lt9611_i2c_write_byte(0xcb,0x69); //Timer 1
|
|
lt9611_i2c_write_byte(0xcc,0x78);
|
|
|
|
/*power consumption for work*/
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x04,0xf0);
|
|
lt9611_i2c_write_byte(0x06,0xf0);
|
|
lt9611_i2c_write_byte(0x0a,0x80);
|
|
lt9611_i2c_write_byte(0x0b,0x46); //csc clk
|
|
lt9611_i2c_write_byte(0x0d,0xef);
|
|
lt9611_i2c_write_byte(0x11,0xfa);
|
|
}
|
|
|
|
void LT9611_MIPI_Input_Analog(void)//xuxi
|
|
{
|
|
//mipi mode
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x06,0x60); //port A rx current
|
|
lt9611_i2c_write_byte(0x07,0x3f); //eq
|
|
lt9611_i2c_write_byte(0x08,0x3f); //eq
|
|
lt9611_i2c_write_byte(0x09,0x09);
|
|
|
|
lt9611_i2c_write_byte(0x0a,0xfe); //port A ldo voltage set
|
|
lt9611_i2c_write_byte(0x0b,0xbf); //enable port A lprx
|
|
|
|
lt9611_i2c_write_byte(0x11,0x60); //port B rx current
|
|
lt9611_i2c_write_byte(0x12,0x3f); //eq
|
|
lt9611_i2c_write_byte(0x13,0x3f); //eq
|
|
lt9611_i2c_write_byte(0x15,0xfe); //port B ldo voltage set
|
|
lt9611_i2c_write_byte(0x16,0xbf); //enable port B lprx
|
|
|
|
lt9611_i2c_write_byte(0x1c,0x03); //PortA clk lane no-LP mode.
|
|
lt9611_i2c_write_byte(0x20,0x03); //PortB clk lane no-LP mode.
|
|
}
|
|
|
|
void LT9611_MIPI_Input_Digtal(void) //weiguo
|
|
{
|
|
CVI_U8 lanes;
|
|
lanes = lt9611.mipi_lane_cnt;
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_MIPI_Input_Digtal: lt9611 set mipi lanes = %d", lanes);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x4f,0x80); //[7] = Select ad_txpll_d_clk.
|
|
lt9611_i2c_write_byte(0x50,0x10);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x00,lanes);
|
|
lt9611_i2c_write_byte(0x02,0x08); //settle
|
|
lt9611_i2c_write_byte(0x06,0x08); //settle
|
|
|
|
if(1)//(P10) //single_port_mipi
|
|
{
|
|
lt9611_i2c_write_byte(0x0a,0x00); //1=dual_lr, 0=dual_en
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_MIPI_Input_Digtal: lt9611 set mipi ports = 1\n");
|
|
}
|
|
else //dual_port_mipi
|
|
{
|
|
lt9611_i2c_write_byte(0x0a,0x03); //1=dual_lr, 0=dual_en
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_MIPI_Input_Digtal: lt9611 set mipi port = 2\n");
|
|
}
|
|
|
|
#if 1
|
|
if(lt9611.mipi_mode==csi)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_MIPI_Input_Digtal: LT9611.mipi_mode = csi\n");
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x08,0x10); //csi_en
|
|
lt9611_i2c_write_byte(0x2c,0x40); //csi_sel
|
|
|
|
if(lt9611.input_color_space == RGB888)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x1c,0x01);
|
|
}
|
|
}
|
|
else
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_MIPI_Input_Digtal: LT9611.mipi_mode = dsi\n");
|
|
#endif
|
|
}
|
|
|
|
void LT9611_Video_Check(void) //dsren
|
|
{
|
|
#if 1
|
|
CVI_U8 mipi_video_format=0x00;
|
|
CVI_U16 h_act, h_act_a ,h_act_b, v_act,v_tal;
|
|
CVI_U16 h_total_sysclk;
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82); // top video check module
|
|
h_total_sysclk = lt9611_i2c_read_byte(0x86);
|
|
h_total_sysclk = (h_total_sysclk<<8) + lt9611_i2c_read_byte(0x87);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "\33[32m\n");
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "-----------------------------------------------------------------------------\n");
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Video_Check: h_total_sysclk = %d",h_total_sysclk);
|
|
|
|
v_act=lt9611_i2c_read_byte(0x82);
|
|
v_act=(v_act<<8)+lt9611_i2c_read_byte(0x83);
|
|
v_tal=lt9611_i2c_read_byte(0x6c);
|
|
v_tal=(v_tal<<8)+lt9611_i2c_read_byte(0x6d);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
h_act_a = lt9611_i2c_read_byte(0x82);
|
|
h_act_a = (h_act_a<<8)+lt9611_i2c_read_byte(0x83);
|
|
|
|
h_act_b = lt9611_i2c_read_byte(0x86);
|
|
h_act_b =(h_act_b<<8)+lt9611_i2c_read_byte(0x87);
|
|
|
|
|
|
if(lt9611.input_color_space==YUV422)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Video_Check: lt9611.input_color_space = YUV422\n");
|
|
h_act_a /= 2;
|
|
h_act_b /= 2;
|
|
}
|
|
else if(lt9611.input_color_space==RGB888)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Video_Check: lt9611.input_color_space = RGB888\n");
|
|
h_act_a /= 3;
|
|
h_act_b /= 3;
|
|
}
|
|
|
|
mipi_video_format=lt9611_i2c_read_byte(0x88);
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Video_Check: h_act_a, h_act_b, v_act, v_tal: %d, %d, %d, %d, ",h_act_a, h_act_b, v_act, v_tal);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Video_Check: mipi_video_format: 0x%x",mipi_video_format);
|
|
|
|
if(0)//(P10 == 0) //dual port.
|
|
h_act = h_act_a + h_act_b;
|
|
else
|
|
h_act = h_act_a;
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Video_Check: Video_Format =\n");
|
|
///////////////////////formate detect///////////////////////////////////
|
|
|
|
//DTV
|
|
if((h_act==video_640x480_60Hz.hact)&&(v_act==video_640x480_60Hz.vact))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_640x480_60Hz \n");
|
|
Video_Format=video_640x480_60Hz_vic1;
|
|
video = &video_640x480_60Hz;
|
|
}
|
|
else if((h_act==(video_720x480_60Hz.hact))&&(v_act==video_720x480_60Hz.vact))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_720x480_60Hz \n");
|
|
Video_Format=video_720x480_60Hz_vic3;
|
|
video = &video_720x480_60Hz;
|
|
}
|
|
|
|
else if((h_act==(video_720x576_50Hz.hact))&&(v_act==video_720x576_50Hz.vact))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_720x576_50Hz \n");
|
|
Video_Format=video_720x576_50Hz_vic;
|
|
video = &video_720x576_50Hz;
|
|
}
|
|
|
|
else if((h_act==video_1280x720_60Hz.hact) && (v_act==video_1280x720_60Hz.vact))
|
|
{
|
|
if(h_total_sysclk < 630)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1280x720_60Hz \n");
|
|
Video_Format=video_1280x720_60Hz_vic4;
|
|
video = &video_1280x720_60Hz;
|
|
}
|
|
else if(h_total_sysclk < 750)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1280x720_50Hz \n");
|
|
Video_Format=video_1280x720_50Hz_vic;
|
|
video = &video_1280x720_50Hz;
|
|
}
|
|
else if(h_total_sysclk < 1230)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1280x720_30Hz \n");
|
|
Video_Format=video_1280x720_30Hz_vic;
|
|
video = &video_1280x720_30Hz;
|
|
}
|
|
}
|
|
|
|
else if((h_act==(video_1280x800_60Hz.hact))&&(v_act==video_1280x800_60Hz.vact))
|
|
{
|
|
if(h_total_sysclk < 560)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1280x800_60Hz \n");
|
|
Video_Format = video_other;
|
|
video = &video_1280x800_60Hz;
|
|
}
|
|
}
|
|
|
|
else if((h_act==video_1920x1080_60Hz.hact) && (v_act==video_1920x1080_60Hz.vact))//1080P
|
|
{
|
|
if(h_total_sysclk < 430)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1920x1080_60Hz \n");
|
|
Video_Format=video_1920x1080_60Hz_vic16;
|
|
video = &video_1920x1080_60Hz;
|
|
}
|
|
|
|
else if(h_total_sysclk < 510)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1920x1080_50Hz \n");
|
|
Video_Format=video_1920x1080_50Hz_vic;
|
|
video = &video_1920x1080_50Hz;
|
|
}
|
|
|
|
else if(h_total_sysclk < 830)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1920x1080_30Hz \n");
|
|
Video_Format=video_1920x1080_30Hz_vic;
|
|
video = &video_1920x1080_30Hz;
|
|
}
|
|
|
|
else if(h_total_sysclk < 980)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1920x1080_25Hz \n");
|
|
Video_Format=video_1920x1080_25Hz_vic;
|
|
video = &video_1920x1080_25Hz;
|
|
}
|
|
|
|
else if(h_total_sysclk < 1030)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1920x1080_24Hz \n");
|
|
Video_Format=video_1920x1080_24Hz_vic;
|
|
video = &video_1920x1080_24Hz;
|
|
}
|
|
}
|
|
else if((h_act==video_3840x2160_30Hz.hact) && (v_act==video_3840x2160_30Hz.vact)) //2160P
|
|
{
|
|
if(h_total_sysclk < 430)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_3840x2160_30Hz \n");
|
|
Video_Format=video_3840x2160_30Hz_vic;
|
|
video = &video_3840x2160_30Hz;
|
|
}
|
|
else if(h_total_sysclk < 490)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_3840x2160_25Hz \n");
|
|
Video_Format=video_3840x2160_25Hz_vic;
|
|
video = &video_3840x2160_25Hz;
|
|
}
|
|
else if(h_total_sysclk < 520)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_3840x2160_24Hz \n");
|
|
Video_Format=video_3840x2160_24Hz_vic;
|
|
video = &video_3840x2160_24Hz;
|
|
}
|
|
}
|
|
else if((h_act==(video_1024x768_60Hz.hact))&&(v_act==video_1024x768_60Hz.vact))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1024x768_60Hz \n");
|
|
Video_Format = video_other;
|
|
video = &video_1024x768_60Hz;
|
|
}
|
|
else if((h_act==(video_1280x1024_60Hz.hact))&&(v_act==video_1280x1024_60Hz.vact))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1280x1024_60Hz \n");
|
|
Video_Format = video_other;
|
|
video = &video_1280x1024_60Hz;
|
|
}
|
|
else if((h_act==(video_1600x1200_60Hz.hact))&&(v_act==video_1600x1200_60Hz.vact))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1600x1200_60Hz \n");
|
|
Video_Format = video_other;
|
|
video = &video_1600x1200_60Hz;
|
|
}
|
|
else if((h_act==video_1200x1920_60Hz.hact)&&(v_act==video_1200x1920_60Hz.vact))//&&
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1200x1920_60Hz \n");
|
|
Video_Format = video_other;
|
|
video = &video_1200x1920_60Hz;
|
|
}
|
|
else if((h_act==video_1920x720_60Hz.hact)&&(v_act==video_1920x720_60Hz.vact))//&&
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " video_1920x720_60Hz \n");
|
|
Video_Format = video_other;
|
|
video = &video_1920x720_60Hz;
|
|
}
|
|
else
|
|
{
|
|
Video_Format = video_none;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " unknown video format \n");
|
|
}
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "-----------------------------------------------------------------------------\n");
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void LT9611_MIPI_Video_Timing(struct video_timing *video_format) //weiguo
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x0d,(CVI_U8)(video_format->vtotal/256));
|
|
lt9611_i2c_write_byte(0x0e,(CVI_U8)(video_format->vtotal%256));//vtotal
|
|
lt9611_i2c_write_byte(0x0f,(CVI_U8)(video_format->vact/256));
|
|
lt9611_i2c_write_byte(0x10,(CVI_U8)(video_format->vact%256)); //vactive
|
|
lt9611_i2c_write_byte(0x11,(CVI_U8)(video_format->htotal/256));
|
|
lt9611_i2c_write_byte(0x12,(CVI_U8)(video_format->htotal%256));//htotal
|
|
lt9611_i2c_write_byte(0x13,(CVI_U8)(video_format->hact/256));
|
|
lt9611_i2c_write_byte(0x14,(CVI_U8)(video_format->hact%256)); //hactive
|
|
lt9611_i2c_write_byte(0x15,(CVI_U8)(video_format->vs%256)); //vsa
|
|
lt9611_i2c_write_byte(0x16,(CVI_U8)(video_format->hs%256)); //hsa
|
|
lt9611_i2c_write_byte(0x17,(CVI_U8)(video_format->vfp%256)); //vfp
|
|
lt9611_i2c_write_byte(0x18,(CVI_U8)((video_format->vs+video_format->vbp)%256)); //vss
|
|
lt9611_i2c_write_byte(0x19,(CVI_U8)(video_format->hfp%256)); //hfp
|
|
lt9611_i2c_write_byte(0x1a,(CVI_U8)(((video_format->hfp/256)<<4)+(video_format->hs+video_format->hbp)/256)); //20180901
|
|
lt9611_i2c_write_byte(0x1b,(CVI_U8)((video_format->hs+video_format->hbp)%256)); //hss
|
|
}
|
|
|
|
void LT9611_MIPI_Pcr(struct video_timing *video_format) //weiguo
|
|
{
|
|
CVI_U8 POL;
|
|
CVI_U16 hact;
|
|
hact = video_format->hact;
|
|
POL = (video_format-> h_polarity)*0x02 + (video_format-> v_polarity);
|
|
POL = ~POL;
|
|
POL &= 0x03;
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
|
|
// if(P10 == 0) //dual port.
|
|
if(0) //dual port.
|
|
{
|
|
hact = (hact>>2);
|
|
hact += 0x50;
|
|
|
|
hact = (0x3e0>hact ? hact:0x3e0);
|
|
|
|
lt9611_i2c_write_byte(0x0b,(CVI_U8)(hact >>8)); //vsync mode
|
|
lt9611_i2c_write_byte(0x0c,(CVI_U8)hact); //=1/4 hact
|
|
//hact -=0x40;
|
|
lt9611_i2c_write_byte(0x48,(CVI_U8)(hact >>8)); //de mode delay
|
|
lt9611_i2c_write_byte(0x49,(CVI_U8)(hact)); //
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0x0b,0x01); //vsync read delay(reference value)
|
|
lt9611_i2c_write_byte(0x0c,0x10); //
|
|
|
|
lt9611_i2c_write_byte(0x48,0x00); //de mode delay
|
|
lt9611_i2c_write_byte(0x49,0x81); //=1/4 hact
|
|
}
|
|
|
|
/* stage 1 */
|
|
lt9611_i2c_write_byte(0x21,0x4a); //bit[3:0] step[11:8]
|
|
//lt9611_i2c_write_byte(0x22,0x40);//step[7:0]
|
|
|
|
lt9611_i2c_write_byte(0x24,0x71); //bit[7:4]v/h/de mode; line for clk stb[11:8]
|
|
lt9611_i2c_write_byte(0x25,0x30); //line for clk stb[7:0]
|
|
|
|
lt9611_i2c_write_byte(0x2a,0x01); //clk stable in
|
|
|
|
/* stage 2 */
|
|
lt9611_i2c_write_byte(0x4a,0x40); //offset //0x10
|
|
lt9611_i2c_write_byte(0x1d,(0x10|POL)); //PCR de mode step setting.
|
|
|
|
/* MK limit */
|
|
|
|
switch(Video_Format)
|
|
{
|
|
case video_3840x1080_60Hz_vic:
|
|
case video_3840x2160_30Hz_vic:
|
|
case video_3840x2160_25Hz_vic:
|
|
case video_3840x2160_24Hz_vic:
|
|
case video_2560x1600_60Hz_vic:
|
|
case video_2560x1440_60Hz_vic:
|
|
case video_2560x1080_60Hz_vic:
|
|
break;
|
|
case video_1920x1080_60Hz_vic16:
|
|
case video_1920x1080_30Hz_vic:
|
|
case video_1280x720_60Hz_vic4:
|
|
case video_1280x720_30Hz_vic:
|
|
break;
|
|
case video_720x480_60Hz_vic3:
|
|
case video_640x480_60Hz_vic1:
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x0b,0x02);
|
|
lt9611_i2c_write_byte(0x0c,0x40);
|
|
lt9611_i2c_write_byte(0x48,0x01);
|
|
lt9611_i2c_write_byte(0x49,0x10);
|
|
lt9611_i2c_write_byte(0x24,0x70);
|
|
lt9611_i2c_write_byte(0x25,0x80);
|
|
lt9611_i2c_write_byte(0x2a,0x10);
|
|
lt9611_i2c_write_byte(0x2b,0x80);
|
|
lt9611_i2c_write_byte(0x23,0x28); //
|
|
lt9611_i2c_write_byte(0x4a,0x10);
|
|
lt9611_i2c_write_byte(0x1d,0xf3); //
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_MIPI_Pcr: 640x480_60Hz\n");
|
|
break;
|
|
|
|
case video_540x960_60Hz_vic:
|
|
case video_1024x600_60Hz_vic:
|
|
lt9611_i2c_write_byte(0x24,0x70); //bit[7:4]v/h/de mode; line for clk stb[11:8]
|
|
lt9611_i2c_write_byte(0x25,0x80); //line for clk stb[7:0]
|
|
lt9611_i2c_write_byte(0x2a,0x10); //clk stable in
|
|
|
|
/* stage 2 */
|
|
//lt9611_i2c_write_byte(0x23,0x04); //pcr h mode step
|
|
//lt9611_i2c_write_byte(0x4a,0x10); //offset //0x10
|
|
lt9611_i2c_write_byte(0x1d,0xf0); //PCR de mode step setting.
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
LT9611_MIPI_Video_Timing(video);
|
|
|
|
//lt9611_i2c_write_byte(0xff,0x83);
|
|
//lt9611_i2c_write_byte(0x26,pcr_m);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x11,0x5a); //Pcr reset
|
|
//lt9611_i2c_write_byte(0x11,0xfa);
|
|
lt9611_i2c_write_byte(0x11,0xf8);
|
|
}
|
|
|
|
void LT9611_PLL(struct video_timing *video_format) //zhangzhichun
|
|
{
|
|
CVI_U32 pclk;
|
|
CVI_U8 pll_lock_flag, cal_done_flag, band_out;
|
|
CVI_U8 hdmi_post_div;
|
|
CVI_U8 i;
|
|
pclk = video_format->pclk_khz;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_PLL: set rx pll = %d", pclk);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x23,0x40); //Enable LDO and disable PD
|
|
lt9611_i2c_write_byte(0x24,0x62); //0x62, LG25UM58 issue, 20180824
|
|
//lt9611_i2c_write_byte(0x25,0x80); //pre-divider
|
|
lt9611_i2c_write_byte(0x25,0xc2); //pre-divider
|
|
lt9611_i2c_write_byte(0x26,0x55);
|
|
lt9611_i2c_write_byte(0x2c,0x37);
|
|
//lt9611_i2c_write_byte(0x2d,0x99); //txpll_divx_set&da_txpll_freq_set
|
|
//lt9611_i2c_write_byte(0x2e,0x01);
|
|
lt9611_i2c_write_byte(0x2f,0x01);
|
|
//lt9611_i2c_write_byte(0x26,0x55);
|
|
lt9611_i2c_write_byte(0x27,0x66);
|
|
lt9611_i2c_write_byte(0x28,0x88);
|
|
|
|
lt9611_i2c_write_byte(0x2a,0x20); //for U3.
|
|
|
|
if(pclk > 150000)
|
|
{
|
|
lt9611_i2c_write_byte(0x2d,0x88);
|
|
hdmi_post_div = 0x01;
|
|
}
|
|
else if(pclk > 70000)
|
|
{
|
|
lt9611_i2c_write_byte(0x2d,0x99);
|
|
hdmi_post_div = 0x02;
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0x2d,0xaa); //0xaa
|
|
hdmi_post_div = 0x04;
|
|
}
|
|
|
|
//pcr_m = (CVI_U8)((pclk*5*hdmi_post_div)/27000);
|
|
//pcr_m --;
|
|
|
|
pcr_m = 20*hdmi_post_div;
|
|
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_PLL: pcr_m = 0x%x, hdmi_post_div = %d", pcr_m, hdmi_post_div); //Hex
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x2d,0x40); //M up limit
|
|
lt9611_i2c_write_byte(0x31,0x08); //M down limit
|
|
lt9611_i2c_write_byte(0x26,0x80|pcr_m); /* fixed M is to let pll locked*/
|
|
|
|
pclk = pclk / 2;
|
|
lt9611_i2c_write_byte(0xff,0x82); //13.5M
|
|
lt9611_i2c_write_byte(0xe3,pclk/65536);
|
|
pclk = pclk % 65536;
|
|
lt9611_i2c_write_byte(0xe4,pclk/256);
|
|
lt9611_i2c_write_byte(0xe5,pclk%256);
|
|
|
|
lt9611_i2c_write_byte(0xde,0x20); // pll cal en, start calibration
|
|
lt9611_i2c_write_byte(0xde,0xe0);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x11,0x5a); /* Pcr clk reset */
|
|
lt9611_i2c_write_byte(0x11,0xfa);
|
|
lt9611_i2c_write_byte(0x16,0xf2); /* pll cal digital reset */
|
|
lt9611_i2c_write_byte(0x18,0xdc); /* pll analog reset */
|
|
lt9611_i2c_write_byte(0x18,0xfc);
|
|
lt9611_i2c_write_byte(0x16,0xf3); /*start calibration*/
|
|
|
|
/* pll lock status */
|
|
for(i = 0; i < 6 ; i++)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x16,0xe3); /* pll lock logic reset */
|
|
lt9611_i2c_write_byte(0x16,0xf3);
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
cal_done_flag = lt9611_i2c_read_byte(0xe7);
|
|
band_out = lt9611_i2c_read_byte(0xe6);
|
|
pll_lock_flag = lt9611_i2c_read_byte(0x15);
|
|
|
|
if((pll_lock_flag & 0x80)&&(cal_done_flag & 0x80)&&(band_out != 0xff))
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_PLL: HDMI pll locked band out: 0x%x", band_out);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x11,0x5a); /* Pcr clk reset */
|
|
lt9611_i2c_write_byte(0x11,0xfa);
|
|
lt9611_i2c_write_byte(0x16,0xf2); /* pll cal digital reset */
|
|
lt9611_i2c_write_byte(0x18,0xdc); /* pll analog reset */
|
|
lt9611_i2c_write_byte(0x18,0xfc);
|
|
lt9611_i2c_write_byte(0x16,0xf3); /*start calibration*/
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_PLL: HDMI pll unlocked, reset pll\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void LT9611_HDMI_TX_Phy(void) //xyji
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x30,0x6a);
|
|
if(lt9611.hdmi_coupling_mode==ac_mode)
|
|
{
|
|
lt9611_i2c_write_byte(0x31,0x73); //DC: 0x44, AC:0x73
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_TX_Phy: AC couple\n");
|
|
}
|
|
else //lt9611.hdmi_coupling_mode==dc_mode
|
|
{
|
|
lt9611_i2c_write_byte(0x31,0x44);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_TX_Phy: DC couple\n");
|
|
}
|
|
lt9611_i2c_write_byte(0x32,0x4a);
|
|
lt9611_i2c_write_byte(0x33,0x0b);
|
|
lt9611_i2c_write_byte(0x34,0x00);
|
|
lt9611_i2c_write_byte(0x35,0x00);
|
|
lt9611_i2c_write_byte(0x36,0x00);
|
|
lt9611_i2c_write_byte(0x37,0x44);
|
|
lt9611_i2c_write_byte(0x3f,0x0f);
|
|
lt9611_i2c_write_byte(0x40,0x98); //clk swing
|
|
lt9611_i2c_write_byte(0x41,0x98); //D0 swing
|
|
lt9611_i2c_write_byte(0x42,0x98); //D1 swing
|
|
lt9611_i2c_write_byte(0x43,0x98); //D2 swing
|
|
lt9611_i2c_write_byte(0x44,0x0a);
|
|
}
|
|
|
|
void LT9611_HDCP_Init(void) //luodexing
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x85);
|
|
lt9611_i2c_write_byte(0x07,0x1f);
|
|
lt9611_i2c_write_byte(0x13,0xfe);// [7]=force_hpd, [6]=force_rsen, [5]=vsync_pol, [4]=hsync_pol,
|
|
// [3]=hdmi_mode, [2]=no_accs_when_rdy, [1]=skip_wt_hdmi
|
|
lt9611_i2c_write_byte(0x17,0x0f);// [7]=ri_short_read, [3]=sync_pol_mode, [2]=srm_chk_done,
|
|
// [1]=bksv_srm_pass, [0]=ksv_list_vld
|
|
lt9611_i2c_write_byte(0x15,0x05);
|
|
//lt9611_i2c_write_byte(0x15,0x65);// [7]=key_ddc_st_sel, [6]=tx_hdcp_en,[5]=tx_auth_en, [4]=tx_re_auth
|
|
}
|
|
|
|
void LT9611_HDCP_Enable(void) //luodexing
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x14,0x7f);
|
|
lt9611_i2c_write_byte(0x14,0xff);
|
|
lt9611_i2c_write_byte(0xff,0x85);
|
|
lt9611_i2c_write_byte(0x15,0x01); //disable HDCP
|
|
lt9611_i2c_write_byte(0x15,0x71); //enable HDCP
|
|
lt9611_i2c_write_byte(0x15,0x65); //enable HDCP
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDCP_Enable: On\n");
|
|
}
|
|
|
|
void LT9611_HDCP_Disable(void) //luodexing
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x85);
|
|
lt9611_i2c_write_byte(0x15,0x45); //enable HDCP
|
|
}
|
|
|
|
void LT9611_HDMI_Out_Enable(void) //dsren
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x23,0x40);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0xde,0x20);
|
|
lt9611_i2c_write_byte(0xde,0xe0);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x18,0xdc); /* txpll sw rst */
|
|
lt9611_i2c_write_byte(0x18,0xfc);
|
|
lt9611_i2c_write_byte(0x16,0xf1); /* txpll calibration rest */
|
|
lt9611_i2c_write_byte(0x16,0xf3);
|
|
|
|
lt9611_i2c_write_byte(0x11,0x5a); //Pcr reset
|
|
lt9611_i2c_write_byte(0x11,0xf8);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x30,0xea);
|
|
|
|
if(lt9611.hdcp_encryption == hdcp_enable)
|
|
{
|
|
LT9611_HDCP_Enable();
|
|
}
|
|
else
|
|
{
|
|
LT9611_HDCP_Disable();
|
|
}
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_Out_Enable\n");
|
|
}
|
|
|
|
void LT9611_HDMI_Out_Disable(void) //dsren
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x30,0x00); /* Txphy PD */
|
|
lt9611_i2c_write_byte(0x23,0x80); /* Txpll PD */
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_Out_Disable\n");
|
|
LT9611_HDCP_Disable();
|
|
}
|
|
|
|
void LT9611_HDMI_TX_Digital(struct video_timing *video_format) //dsren
|
|
{
|
|
//bool hdmi_mode = lt9611->hdmi_mode;
|
|
CVI_U8 VIC = video_format->vic;
|
|
CVI_U8 AR = video_format->aspact_ratio;
|
|
CVI_U8 pb0,pb2,pb4;
|
|
CVI_U8 infoFrame_en;
|
|
|
|
infoFrame_en = (AIF_PKT_EN|AVI_PKT_EN|SPD_PKT_EN);
|
|
//MPEG_PKT_EN,AIF_PKT_EN,SPD_PKT_EN,AVI_PKT_EN,UD0_PKT_EN,UD1_PKT_EN
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_TX_Digital: infoFrame_en = 0x%x",infoFrame_en);
|
|
|
|
pb2 = (AR<<4) + 0x08;
|
|
pb4 = VIC;
|
|
|
|
pb0 = ((pb2 + pb4) <= 0x5f)?(0x5f - pb2 - pb4):(0x15f - pb2 - pb4);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
if(lt9611.hdmi_mode == HDMI)
|
|
{
|
|
lt9611_i2c_write_byte(0xd6,0x8e); //sync polarity
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_TX_Digital: HMDI mode = HDMI\n");
|
|
}
|
|
else if(lt9611.hdmi_mode == DVI)
|
|
{
|
|
lt9611_i2c_write_byte(0xd6,0x0e); //sync polarity
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDMI_TX_Digital: HMDI mode = DVI\n");
|
|
}
|
|
|
|
if(lt9611.audio_out==audio_i2s)
|
|
{
|
|
lt9611_i2c_write_byte(0xd7,0x04);
|
|
}
|
|
|
|
if(lt9611.audio_out==audio_spdif)
|
|
{
|
|
lt9611_i2c_write_byte(0xd7,0x80);
|
|
}
|
|
|
|
//AVI
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x43,pb0); //AVI_PB0
|
|
|
|
//lt9611_i2c_write_byte(0x44,0x10);//AVI_PB1
|
|
lt9611_i2c_write_byte(0x45,pb2); //AVI_PB2
|
|
lt9611_i2c_write_byte(0x47,pb4); //AVI_PB4
|
|
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x10,0x02); //data iland
|
|
lt9611_i2c_write_byte(0x12,0x64); //act_h_blank
|
|
|
|
//VS_IF, 4k 30hz need send VS_IF packet.
|
|
if(VIC == 95)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x3d,infoFrame_en|UD0_PKT_EN); //UD1 infoframe enable //revise on 20200715
|
|
|
|
lt9611_i2c_write_byte(0x74,0x81); //HB0
|
|
lt9611_i2c_write_byte(0x75,0x01); //HB1
|
|
lt9611_i2c_write_byte(0x76,0x05); //HB2
|
|
lt9611_i2c_write_byte(0x77,0x49); //PB0
|
|
lt9611_i2c_write_byte(0x78,0x03); //PB1
|
|
lt9611_i2c_write_byte(0x79,0x0c); //PB2
|
|
lt9611_i2c_write_byte(0x7a,0x00); //PB3
|
|
lt9611_i2c_write_byte(0x7b,0x20); //PB4
|
|
lt9611_i2c_write_byte(0x7c,0x01); //PB5
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x3d,infoFrame_en); //UD1 infoframe enable
|
|
}
|
|
|
|
if(infoFrame_en&&SPD_PKT_EN)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0xc0,0x83); //HB0
|
|
lt9611_i2c_write_byte(0xc1,0x01); //HB1
|
|
lt9611_i2c_write_byte(0xc2,0x19); //HB2
|
|
|
|
lt9611_i2c_write_byte(0xc3,0x00); //PB0
|
|
lt9611_i2c_write_byte(0xc4,0x01); //PB1
|
|
lt9611_i2c_write_byte(0xc5,0x02); //PB2
|
|
lt9611_i2c_write_byte(0xc6,0x03); //PB3
|
|
lt9611_i2c_write_byte(0xc7,0x04); //PB4
|
|
lt9611_i2c_write_byte(0xc8,0x00); //PB5
|
|
}
|
|
}
|
|
|
|
void LT9611_CSC(void)
|
|
{
|
|
if(lt9611.input_color_space == YUV422)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0xb9,0x18);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_CSC: Ypbpr 422 to RGB888\n");
|
|
}
|
|
}
|
|
|
|
|
|
void LT9611_Audio_Init(void) //sujin
|
|
{
|
|
#if 1
|
|
if(lt9611.audio_out==audio_i2s)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "Audio inut = I2S 2ch\n");
|
|
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x06,0x08);
|
|
lt9611_i2c_write_byte(0x07,0x10);
|
|
|
|
//48K sampling frequency
|
|
lt9611_i2c_write_byte(0x0f,0x2b); //0x2b: 48K, 0xab:96K
|
|
lt9611_i2c_write_byte(0x34,0xd4); //CTS_N 20180823 0xd5: sclk = 32fs, 0xd4: sclk = 64fs
|
|
|
|
lt9611_i2c_write_byte(0x35,0x00); // N value = 6144
|
|
lt9611_i2c_write_byte(0x36,0x18);
|
|
lt9611_i2c_write_byte(0x37,0x00);
|
|
}
|
|
|
|
if(lt9611.audio_out==audio_spdif)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "Audio inut = SPDIF\n");
|
|
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x06,0x0c);
|
|
lt9611_i2c_write_byte(0x07,0x10);
|
|
|
|
lt9611_i2c_write_byte(0x34,0xd4); //CTS_N
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void LT9611_Read_EDID(void) //luodexing
|
|
{
|
|
#ifdef _enable_read_edid_
|
|
CVI_U8 i,j, edid_data;
|
|
CVI_U8 extended_flag = 00;
|
|
|
|
memset(Sink_EDID,0,sizeof Sink_EDID);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x85);
|
|
//lt9611_i2c_write_byte(0x02,0x0a); //I2C 100K
|
|
lt9611_i2c_write_byte(0x03,0xc9);
|
|
lt9611_i2c_write_byte(0x04,0xa0); //0xA0 is EDID device address
|
|
lt9611_i2c_write_byte(0x05,0x00); //0x00 is EDID offset address
|
|
lt9611_i2c_write_byte(0x06,0x20); //length for read
|
|
lt9611_i2c_write_byte(0x14,0x7f);
|
|
|
|
for(i=0;i < 8;i++) // block 0 & 1
|
|
{
|
|
lt9611_i2c_write_byte(0x05,i*32); //0x00 is EDID offset address
|
|
lt9611_i2c_write_byte(0x07,0x36);
|
|
lt9611_i2c_write_byte(0x07,0x34); //0x31
|
|
lt9611_i2c_write_byte(0x07,0x37); //0x37
|
|
Timer0_Delay1ms(5); // wait 5ms for reading edid data.
|
|
if(lt9611_i2c_read_byte(0x40)&0x02) //KEY_DDC_ACCS_DONE=1
|
|
{
|
|
if(lt9611_i2c_read_byte(0x40)&0x50)//DDC No Ack or Abitration lost
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "read edid failed: no ack\n");
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
for(j=0; j<32; j++)
|
|
{
|
|
edid_data = lt9611_i2c_read_byte(0x83);
|
|
Sink_EDID[i*32+j]= edid_data; // write edid data to Sink_EDID[];
|
|
if((i == 3)&&( j == 30))
|
|
{
|
|
extended_flag = edid_data & 0x03;
|
|
}
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "%x,",edid_data);
|
|
}
|
|
if(i == 3)
|
|
{
|
|
if(extended_flag < 1) //no block 1, stop reading edid.
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "read edid failed: accs not done\n");
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
if(extended_flag < 2) //no block 2, stop reading edid.
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
for(i=0;i< 8;i++) // // block 2 & 3
|
|
{
|
|
lt9611_i2c_write_byte(0x05,i*32); //0x00 is EDID offset address
|
|
lt9611_i2c_write_byte(0x07,0x76); //0x31
|
|
lt9611_i2c_write_byte(0x07,0x74); //0x31
|
|
lt9611_i2c_write_byte(0x07,0x77); //0x37
|
|
Timer0_Delay1ms(5); // wait 5ms for reading edid data.
|
|
if(lt9611_i2c_read_byte(0x40)&0x02) //KEY_DDC_ACCS_DONE=1
|
|
{
|
|
if(lt9611_i2c_read_byte(0x40)&0x50)//DDC No Ack or Abitration lost
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "read edid failed: no ack\n");
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
for(j=0; j<32; j++)
|
|
{
|
|
edid_data = lt9611_i2c_read_byte(0x83);
|
|
//Sink_EDID[256+i*32+j]= edid_data; // write edid data to Sink_EDID[];
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "%x,",edid_data);
|
|
}
|
|
if(i == 3)
|
|
{
|
|
if(extended_flag < 3) //no block 1, stop reading edid.
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "read edid failed: accs not done\n");
|
|
goto end;
|
|
}
|
|
}
|
|
end:
|
|
lt9611_i2c_write_byte(0x03,0xc2);
|
|
lt9611_i2c_write_byte(0x07,0x1f);
|
|
#endif
|
|
}
|
|
|
|
void LT9611_load_hdcp_key(void) //luodexing
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x85);
|
|
lt9611_i2c_write_byte(0x00,0x85);
|
|
//lt9611_i2c_write_byte(0x02,0x0a); //I2C 100K
|
|
lt9611_i2c_write_byte(0x03,0xc0);
|
|
lt9611_i2c_write_byte(0x03,0xc3);
|
|
lt9611_i2c_write_byte(0x04,0xa0); //0xA0 is eeprom device address
|
|
lt9611_i2c_write_byte(0x05,0x00); //0x00 is eeprom offset address
|
|
lt9611_i2c_write_byte(0x06,0x20); //length for read
|
|
lt9611_i2c_write_byte(0x14,0xff);
|
|
|
|
lt9611_i2c_write_byte(0x07,0x11); //0x31
|
|
lt9611_i2c_write_byte(0x07,0x17); //0x37
|
|
Timer0_Delay1ms(50); // wait 5ms for loading key.
|
|
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_load_hdcp_key: 0x%02bx",lt9611_i2c_read_byte(0x40));
|
|
|
|
if((lt9611_i2c_read_byte(0x40)&0x81) == 0x81)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_load_hdcp_key: external key valid\n");
|
|
}
|
|
else
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_load_hdcp_key: external key unvalid, using internal test key!\n");
|
|
}
|
|
|
|
lt9611_i2c_write_byte(0x03,0xc2);
|
|
lt9611_i2c_write_byte(0x07,0x1f);
|
|
}
|
|
|
|
bool LT9611_Get_HPD_Status(void)
|
|
{
|
|
CVI_U8 reg_825e;
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
reg_825e = lt9611_i2c_read_byte(0x5e);
|
|
|
|
if((reg_825e&0x04) == 0x04) //20200727
|
|
{
|
|
//Tx_HPD=1;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
//Tx_HPD=0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
//CEC: start
|
|
void LT9611_HDMI_CEC_ON(bool enable)
|
|
{
|
|
if(enable){
|
|
/* cec init */
|
|
lt9611_i2c_write_byte(0xff, 0x80);
|
|
lt9611_i2c_write_byte(0x0d, 0xff);
|
|
lt9611_i2c_write_byte(0x15, 0xf1); //reset cec logic
|
|
lt9611_i2c_write_byte(0x15, 0xf9);
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xfe, 0xa5); //clk div
|
|
}
|
|
else{
|
|
lt9611_i2c_write_byte(0xff, 0x80);
|
|
lt9611_i2c_write_byte(0x15, 0xf1);
|
|
}
|
|
}
|
|
|
|
void lt9611_cec_logical_reset(void)
|
|
{
|
|
lt9611_i2c_write_byte(0xff, 0x80);
|
|
lt9611_i2c_write_byte(0x15, 0xf1); //reset cec logic
|
|
lt9611_i2c_write_byte(0x15, 0xf9);
|
|
}
|
|
|
|
|
|
void lt9611_cec_msg_set_logical_address(struct cec_msg *cec_msg)
|
|
{
|
|
CVI_U8 logical_address;
|
|
/*
|
|
0xf8, 0xf7 //Register
|
|
0x00, 0x01, //LA 0
|
|
0x00, 0x02, //LA 1
|
|
0x00, 0x03, //LA 2
|
|
0x00, 0x04, //LA 3
|
|
0x00, 0x10, //LA 4
|
|
0x00, 0x20, //LA 5
|
|
0x00, 0x30, //LA 6
|
|
0x00, 0x40, //LA 7
|
|
0x01, 0x00, //LA 8
|
|
0x02, 0x00, //LA 9
|
|
0x03, 0x00, //LA 10
|
|
0x04, 0x00, //LA 11
|
|
0x10, 0x00, //LA 12
|
|
0x20, 0x00, //LA 13
|
|
0x30, 0x00, //LA 14
|
|
0x40, 0x00 //LA 15
|
|
*/
|
|
|
|
if(!cec_msg->la_allocation_done)
|
|
{
|
|
logical_address = 15;
|
|
}
|
|
else
|
|
{
|
|
logical_address = cec_msg->logical_address;
|
|
}
|
|
|
|
if(logical_address > 15)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_ERR, " LA error!\n");
|
|
return;
|
|
}
|
|
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
|
|
switch(logical_address) {
|
|
case 0:
|
|
lt9611_i2c_write_byte(0xf7, 0x01);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 1:
|
|
lt9611_i2c_write_byte(0xf7, 0x02);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 2:
|
|
lt9611_i2c_write_byte(0xf7, 0x03);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 3:
|
|
lt9611_i2c_write_byte(0xf7, 0x04);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 4:
|
|
lt9611_i2c_write_byte(0xf7, 0x10);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 5:
|
|
lt9611_i2c_write_byte(0xf7, 0x20);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 6:
|
|
lt9611_i2c_write_byte(0xf7, 0x30);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 7:
|
|
lt9611_i2c_write_byte(0xf7, 0x40);
|
|
lt9611_i2c_write_byte(0xf8, 0x00);
|
|
break;
|
|
|
|
case 8:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x01);
|
|
break;
|
|
|
|
case 9:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x02);
|
|
break;
|
|
|
|
case 10:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x03);
|
|
break;
|
|
|
|
case 11:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x04);
|
|
break;
|
|
|
|
case 12:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x10);
|
|
break;
|
|
|
|
case 13:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x20);
|
|
break;
|
|
|
|
case 14:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x30);
|
|
break;
|
|
|
|
case 15:
|
|
lt9611_i2c_write_byte(0xf7, 0x00);
|
|
lt9611_i2c_write_byte(0xf8, 0x40);
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static int do_checksum(const unsigned char *x, CVI_U8 len)
|
|
{
|
|
unsigned char check = x[len];
|
|
unsigned char sum = 0;
|
|
int i;
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "Checksum: 0x%x", check);
|
|
|
|
for (i = 0; i < len; i++)
|
|
sum += x[i];
|
|
|
|
if ((unsigned char)(check + sum) != 0) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " (should be 0x%x)\n", -sum & 0xff);
|
|
return 0;
|
|
}
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " (valid)\n");
|
|
return 1;
|
|
}
|
|
|
|
|
|
int lt9611_parse_physical_address(struct cec_msg *cec_msg, CVI_U8 *edid) // parse edid data from edid.
|
|
{
|
|
// int ret = 0;
|
|
int version;
|
|
int offset = 0;
|
|
int offset_d = 0;
|
|
int tag_code;
|
|
CVI_U16 physical_address;
|
|
|
|
version = edid[0x81];
|
|
offset_d = edid[0x82];
|
|
|
|
if(!do_checksum(edid, 255))
|
|
{
|
|
return 0; //prase_physical_address fail.
|
|
}
|
|
|
|
if (version < 3)
|
|
{
|
|
return 0; //prase_physical_address fail.
|
|
}
|
|
|
|
if (offset_d < 5)
|
|
{
|
|
return 0; //prase_physical_address fail.
|
|
}
|
|
|
|
tag_code = (edid[0x84 + offset] & 0xe0)>>5;
|
|
|
|
while(tag_code != 0x03){
|
|
if((edid[0x84 + offset]&0x1f) == 0 )
|
|
return 0;
|
|
offset += edid[0x84 + offset]&0x1f;
|
|
offset++;
|
|
|
|
if(offset > (offset_d - 4))
|
|
return 0;
|
|
|
|
tag_code = (edid[0x84 + offset] & 0xe0)>>5;
|
|
|
|
}
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "vsdb: 0x%x,0x%x,0x%x", edid[0x84 + offset],edid[0x85 + offset],edid[0x86 + offset]);
|
|
|
|
if((edid[0x84 + offset + 1] == 0x03)&&
|
|
(edid[0x84 + offset + 2] == 0x0c)&&
|
|
(edid[0x84 + offset + 3] == 0x00))
|
|
{
|
|
physical_address = edid[0x84 + offset + 4];
|
|
physical_address = (physical_address<<8) + edid[0x84 + offset + 5];
|
|
cec_msg->physical_address = physical_address;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "prase physical address success! %x",physical_address);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void lt9611_hdmi_cec_read(struct cec_msg *cec_msg) // transfer cec msg from LT9611 regisrer to rx_buffer.
|
|
{
|
|
CVI_U8 size, i;
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xf5, 0x01); //lock rx data buff
|
|
size = lt9611_i2c_read_byte(0xd3);
|
|
cec_msg->rx_data_buff[0] = size;
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "cec rec: \n");
|
|
for(i = 1;i<= size; i++)
|
|
{
|
|
cec_msg->rx_data_buff[i] = lt9611_i2c_read_byte(0xd3 + i);
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "0x%02bx, ",cec_msg->rx_data_buff[i]);
|
|
}
|
|
lt9611_i2c_write_byte(0xf5, 0x00); //unlock rx data buff
|
|
}
|
|
|
|
|
|
void lt9611_hdmi_cec_write(struct cec_msg *cec_msg)// send cec msg which is in tx_buffer.
|
|
{
|
|
CVI_U8 size, i;
|
|
size = cec_msg->tx_data_buff[0];
|
|
cec_msg->retries_times = 0;
|
|
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xf5, 0x01); //lock rx data buff
|
|
lt9611_i2c_write_byte(0xf4, size);
|
|
for(i = 0;i<= size; i++)
|
|
{
|
|
lt9611_i2c_write_byte(0xe4+i, cec_msg->tx_data_buff[1+i]);
|
|
}
|
|
lt9611_i2c_write_byte(0xf9, 0x03); //start send msg
|
|
Timer0_Delay1ms(25*i); //wait HDMI
|
|
lt9611_i2c_write_byte(0xf5, 0x00); //unlock rx data buff
|
|
}
|
|
|
|
|
|
|
|
void lt9611_cec_msg_write_demo(void) //for debug
|
|
{
|
|
CEC_TxData_Buff[0] = 0x05; //data counter to be send
|
|
CEC_TxData_Buff[1] = 0x40; //first cec data(in spec, sender id = 0x05
|
|
//receiver id = 0x00
|
|
CEC_TxData_Buff[2] = 0x84; //second cec data(in spec, it is opcode =0x84)
|
|
CEC_TxData_Buff[3] = 0x10; //parameter of opcode
|
|
CEC_TxData_Buff[4] = 0x00; //parameter of opcode
|
|
CEC_TxData_Buff[5] = 0x05; //parameter of opcode
|
|
|
|
//lt9611_hdmi_cec_write(CEC_TxData_Buff);
|
|
}
|
|
|
|
void lt9611_broad_cast_demo(void) // for debug
|
|
{
|
|
CEC_TxData_Buff[0] = 0x05; //data counter to be send
|
|
CEC_TxData_Buff[1] = 0x40; //first cec data(in spec, sender id = 0x05,
|
|
//receiver id = 0x00
|
|
CEC_TxData_Buff[2] = 0x84; //second cec data(in spec, it is opcode =0x84)
|
|
CEC_TxData_Buff[3] = 0x10; //parameter of opcode
|
|
CEC_TxData_Buff[4] = 0x00; //parameter of opcode
|
|
CEC_TxData_Buff[5] = 0x05; //parameter of opcode
|
|
|
|
//lt9611_hdmi_cec_write(CEC_TxData_Buff);
|
|
}
|
|
|
|
|
|
void lt9611_cec_la_allocation(struct cec_msg *cec_msg) //polling logical address.
|
|
{
|
|
CVI_U8 logical_address;
|
|
|
|
logical_address = cec_msg->logical_address;
|
|
cec_msg->tx_data_buff[0] = 0x01; //data counter to be send
|
|
cec_msg->tx_data_buff[1] = (logical_address<<4)|logical_address;
|
|
//first cec data(in spec, sender id = 0x04,
|
|
//receiver id = 0x04;
|
|
lt9611_hdmi_cec_write(cec_msg);
|
|
}
|
|
|
|
void lt9611_cec_report_physical_address(struct cec_msg *cec_msg) // report physical address.
|
|
{
|
|
cec_msg->tx_data_buff[0] = 0x05; //data counter to be send
|
|
cec_msg->tx_data_buff[1] = (cec_msg->logical_address<<4)|0x0f;
|
|
//first cec data([7:4]=initiator ;[7:4]= destintion)
|
|
cec_msg->tx_data_buff[2] = 0x84; //opcode
|
|
cec_msg->tx_data_buff[3] = (CVI_U8)(cec_msg->physical_address>>8); //parameter of opcode
|
|
cec_msg->tx_data_buff[4] = (CVI_U8)(cec_msg->physical_address); //parameter of opcode
|
|
cec_msg->tx_data_buff[5] = 0x04; //device type = playback device
|
|
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "PA:%bx, %bx",cec_msg->tx_data_buff[3],cec_msg->tx_data_buff[4]);
|
|
lt9611_hdmi_cec_write(cec_msg);
|
|
}
|
|
|
|
|
|
|
|
void lt9611_cec_menu_activate(struct cec_msg *cec_msg) // report physical address.
|
|
{
|
|
cec_msg->tx_data_buff[0] = 0x04; //data counter to be send
|
|
cec_msg->tx_data_buff[1] = (cec_msg->logical_address<<4)|cec_msg->destintion;
|
|
//first cec data([7:4]=initiator ;[7:4]= destintion)
|
|
cec_msg->tx_data_buff[2] = 0x8e; //opcode
|
|
cec_msg->tx_data_buff[3] = 0x00; //parameter of opcode
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "PA:%bx, %bx",cec_msg->tx_data_buff[3],cec_msg->tx_data_buff[4]);
|
|
lt9611_hdmi_cec_write(cec_msg);
|
|
}
|
|
|
|
void lt9611_cec_feature_abort(struct cec_msg *cec_msg, CVI_U8 reason)// report feature abort
|
|
{
|
|
cec_msg->tx_data_buff[0] = 0x03; //data counter to be send
|
|
cec_msg->tx_data_buff[1] = (cec_msg->logical_address<<4)|cec_msg->destintion;
|
|
//first cec data([7:4]=initiator ;[7:4]= destintion)
|
|
cec_msg->tx_data_buff[2] = 0x00; //opcode
|
|
cec_msg->tx_data_buff[3] = reason; //parameter1 of opcode
|
|
|
|
lt9611_hdmi_cec_write(cec_msg);
|
|
}
|
|
|
|
void lt9611_cec_frame_retransmission(struct cec_msg *cec_msg)
|
|
{
|
|
if(cec_msg->retries_times < 5){
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xf9, 0x02);
|
|
lt9611_i2c_write_byte(0xf9, 0x03); //start send msg
|
|
}
|
|
cec_msg->retries_times ++;
|
|
}
|
|
|
|
|
|
void lt9611_cec_device_polling(struct cec_msg *cec_msg)
|
|
{
|
|
static CVI_U8 i;
|
|
if(!cec_msg->la_allocation_done)
|
|
{
|
|
cec_msg->tx_data_buff[0] = 0x01; //data counter to be send
|
|
cec_msg->tx_data_buff[1] = i; //first cec data(in spec, sender id = 0x04,
|
|
//receiver id = 0x04;
|
|
lt9611_hdmi_cec_write(cec_msg);
|
|
if(i >13 )
|
|
cec_msg->la_allocation_done = 1;
|
|
(i>13)?(i=0):(i++);
|
|
}
|
|
}
|
|
|
|
void lt9611_cec_msg_tx_handle(struct cec_msg *cec_msg)
|
|
{
|
|
CVI_U8 cec_status;
|
|
CVI_U8 header;
|
|
CVI_U8 opcode;
|
|
CVI_U8 i;
|
|
cec_status = cec_msg ->cec_status;
|
|
|
|
// if( cec_msg ->send_msg_done) //There is no tx msg to be handled
|
|
// return;
|
|
|
|
if(cec_status&CEC_ERROR_INITIATOR){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "CEC_ERROR_INITIATOR.\n");
|
|
lt9611_cec_logical_reset();
|
|
return;
|
|
}
|
|
|
|
if(cec_status&CEC_ARB_LOST){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "CEC_ARB_LOST.\n"); //lost arbitration
|
|
return;
|
|
}
|
|
|
|
if(cec_status&(CEC_SEND_DONE|CEC_NACK|CEC_ERROR_FOLLOWER)) do {
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "tx_date: \n");
|
|
for(i = 0; i < cec_msg->tx_data_buff[0]; i++)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "0x%x, ",cec_msg->tx_data_buff[i + 1]);
|
|
|
|
|
|
if(cec_status&CEC_SEND_DONE)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "CEC_SEND_DONE >>\n");
|
|
if(cec_status&CEC_NACK)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "NACK >>\n");
|
|
|
|
header = cec_msg ->tx_data_buff[1];
|
|
|
|
if((header == 0x44)||(header == 0x88)||(header == 0xbb)) //logical address allocation
|
|
{
|
|
if(cec_status&CEC_NACK){
|
|
cec_msg ->logical_address = header&0x0f;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "la_allocation_done.\n");
|
|
lt9611_cec_msg_set_logical_address(cec_msg);
|
|
lt9611_cec_report_physical_address(cec_msg);
|
|
}
|
|
|
|
if(cec_status&CEC_SEND_DONE){
|
|
|
|
if(cec_msg->logical_address == 4)// go to next la.
|
|
cec_msg->logical_address = 8;
|
|
else if(cec_msg->logical_address == 8)// go to next la.
|
|
cec_msg->logical_address = 11;
|
|
else if(cec_msg->logical_address == 11) // go to next la.
|
|
cec_msg->logical_address = 4;
|
|
|
|
lt9611_cec_la_allocation(cec_msg);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if(cec_status&(CEC_NACK|CEC_ERROR_FOLLOWER)){
|
|
lt9611_cec_frame_retransmission(cec_msg);
|
|
}
|
|
|
|
if(cec_msg ->tx_data_buff[0] < 2) //check tx data length
|
|
break;
|
|
|
|
opcode = cec_msg ->tx_data_buff[2];
|
|
if(opcode == 0x84){
|
|
cec_msg ->report_physical_address_done = 1;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "report_physical_address.\n");
|
|
}
|
|
|
|
if(opcode == 0x00){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "feature abort\n");
|
|
}
|
|
|
|
} while (0);
|
|
}
|
|
|
|
|
|
void lt9611_cec_msg_rx_parse(struct cec_msg *cec_msg)
|
|
{
|
|
CVI_U8 cec_status;
|
|
CVI_U8 header;
|
|
CVI_U8 opcode;
|
|
CVI_U8 initiator;
|
|
CVI_U8 destintion;
|
|
CVI_U8 i;
|
|
cec_status = cec_msg ->cec_status;
|
|
|
|
// if( cec_msg ->parse_msg_done) //There is no Rx msg to be parsed
|
|
// return;
|
|
|
|
if(cec_status&CEC_ERROR_FOLLOWER){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "CEC_ERROR_FOLLOWER.\n");
|
|
return;
|
|
}
|
|
|
|
if(!(cec_status&CEC_REC_DATA)){
|
|
return;
|
|
}
|
|
|
|
lt9611_hdmi_cec_read(<9611_cec_msg);
|
|
|
|
if(cec_msg ->rx_data_buff[0] < 1) //check rx data length
|
|
return;
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "rx_date: \n");
|
|
for(i = 0; i < cec_msg->rx_data_buff[0]; i++)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "0x%x, ",cec_msg->rx_data_buff[i + 1]);
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "parse <<\n");
|
|
header = cec_msg ->rx_data_buff[1];
|
|
destintion = header&0x0f;
|
|
initiator = (header&0xf0) >> 4;
|
|
//cec_msg ->parse_msg_done = 1;
|
|
|
|
if(header == 0x4f){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "lt9611 broadcast msg.\n");
|
|
}
|
|
|
|
if(cec_msg ->rx_data_buff[0] < 2) //check rx data length
|
|
return;
|
|
|
|
opcode = cec_msg ->rx_data_buff[2];
|
|
|
|
// CECT 12 Invalid Msg Tests
|
|
if((header&0x0f) == 0x0f){
|
|
if((opcode == 0x00)||
|
|
(opcode == 0x83)||
|
|
(opcode == 0x8e)||
|
|
(opcode == 0x90)||
|
|
(opcode == 0xff)){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "Invalid msg, destination address error\n"); //these msg should not be broadcast msg, but they do.
|
|
return;
|
|
}
|
|
}else{
|
|
if((opcode == 0x84)||
|
|
(opcode == 0x84)||
|
|
(opcode == 0x84)){
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "Invalid msg, destination address error\n"); //these msg should be broadcast msg, but they not.
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(opcode == 0xff) //abort
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "abort.\n");
|
|
if(destintion == 0x0f) //ignor broadcast abort msg.
|
|
return;
|
|
cec_msg ->destintion = initiator;
|
|
lt9611_cec_feature_abort(cec_msg, CEC_ABORT_REASON_0);
|
|
}
|
|
|
|
if(opcode == 0x83) //give physical address
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "give physical address.\n");
|
|
lt9611_cec_report_physical_address(cec_msg);
|
|
}
|
|
|
|
if(opcode == 0x90) //report power status
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "report power status.\n");
|
|
if(cec_msg ->rx_data_buff[0] < 3) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "<error:parameters missing\n");
|
|
return; //parameters missing, ignor this msg.
|
|
}
|
|
}
|
|
|
|
if(opcode == 0x8e) //menu status
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "menu status.\n");
|
|
if(cec_msg ->rx_data_buff[0] < 3) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "<error:parameters missing\n");
|
|
return; //parameters missing, ignor this msg.
|
|
}
|
|
}
|
|
|
|
if(opcode == 0x00) //feature abort
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "feature abort.\n");
|
|
if(cec_msg ->rx_data_buff[0] < 3) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "<error:parameters missing\n");
|
|
return; //parameters missing, ignor this msg.
|
|
}
|
|
}
|
|
|
|
if(opcode == 0x9e) //cec version
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "cec version.\n");
|
|
if(cec_msg ->rx_data_buff[0] < 3) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "<error:parameters missing\n");
|
|
return; //parameters missing, ignor this msg.
|
|
}
|
|
}
|
|
|
|
if(opcode == 0x84) //report physical address
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "report physical address.\n");
|
|
if(cec_msg ->rx_data_buff[0] < 5) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "<error:parameters missing\n");
|
|
return; //parameters missing, ignor this msg.
|
|
}
|
|
}
|
|
|
|
if(opcode == 0x86) //set stream path
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "set stream path.\n");
|
|
if(cec_msg ->rx_data_buff[0] < 4) {
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "<error:parameters missing\n");
|
|
return; //parameters missing, ignor this msg.
|
|
}
|
|
lt9611_cec_report_physical_address(cec_msg);
|
|
Timer0_Delay1ms(120);
|
|
lt9611_cec_menu_activate(cec_msg);
|
|
}
|
|
}
|
|
|
|
void lt9611_cec_msg_init(struct cec_msg *cec_msg)
|
|
{
|
|
LT9611_HDMI_CEC_ON(1);
|
|
cec_msg->physical_address = 0x2000;
|
|
cec_msg->logical_address = 4;
|
|
cec_msg->report_physical_address_done = 0;
|
|
cec_msg->la_allocation_done = 0;
|
|
lt9611_cec_msg_set_logical_address(cec_msg);
|
|
}
|
|
|
|
|
|
//CEC: end
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//These function for debug: start
|
|
/////////////////////////////////////////////////////////////
|
|
void LT9611_Frequency_Meter_Byte_Clk(void)
|
|
{
|
|
CVI_U8 temp;
|
|
CVI_U32 reg=0x00;
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "\33[32m\n");
|
|
/* port A byte clk meter */
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0xc7,0x03); //PortA
|
|
Timer0_Delay1ms(50);
|
|
temp = lt9611_i2c_read_byte(0xcd);
|
|
if((temp&0x60)==0x60) /* clk stable */
|
|
{
|
|
reg = (CVI_U32)(temp&0x0f)*65536;
|
|
temp = lt9611_i2c_read_byte(0xce);
|
|
reg = reg + (CVI_U16)temp*256;
|
|
temp = lt9611_i2c_read_byte(0xcf);
|
|
reg = reg + temp;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A byte clk = %d",reg);
|
|
}
|
|
else /* clk unstable */
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A byte clk unstable\n");
|
|
|
|
/* port A reference clock meter */
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0xc7,0x0a);
|
|
Timer0_Delay1ms(50);
|
|
temp = lt9611_i2c_read_byte(0xcd);
|
|
if((temp&0x60)==0x60) /* clk stable */
|
|
{
|
|
reg = (CVI_U32)(temp&0x0f)*65536;
|
|
temp = lt9611_i2c_read_byte(0xce);
|
|
reg =reg + (CVI_U16)temp*256;
|
|
temp = lt9611_i2c_read_byte(0xcf);
|
|
reg = reg + temp;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A reference clock = %d",reg);
|
|
}
|
|
else /* clk unstable */
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A reference clock unstable\n");
|
|
}
|
|
|
|
void LT9611_Htotal_Sysclk(void)
|
|
{
|
|
#ifdef _htotal_stable_check_
|
|
CVI_U16 reg;
|
|
CVI_U8 loopx;
|
|
for(loopx = 0; loopx < 10; loopx++)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
reg = lt9611_i2c_read_byte(0x86);
|
|
reg = reg*256+lt9611_i2c_read_byte(0x87);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "Htotal_Sysclk = %d", reg);
|
|
//printdec_u32(reg);
|
|
}
|
|
#endif
|
|
}
|
|
void LT9611_Pcr_MK_Print(void)
|
|
{
|
|
#ifdef _pcr_mk_printf_
|
|
CVI_U8 loopx;
|
|
for(loopx = 0; loopx < 8; loopx++)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "M:0x%x",lt9611_i2c_read_byte(0x97));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " 0x%x",lt9611_i2c_read_byte(0xb4));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " 0x%x",lt9611_i2c_read_byte(0xb5));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " 0x%x",lt9611_i2c_read_byte(0xb6));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, " 0x%x",lt9611_i2c_read_byte(0xb7));
|
|
Timer0_Delay1ms(1000);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void LT9611_Dphy_debug(void)
|
|
{
|
|
#ifdef _mipi_Dphy_debug_
|
|
CVI_U8 temp;
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
temp = lt9611_i2c_read_byte(0xbc);
|
|
if(temp == 0x55)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane PN is right\n");
|
|
else
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane PN error 0x83bc = 0x%x",temp);
|
|
|
|
temp = lt9611_i2c_read_byte(0x99);
|
|
if(temp == 0xb8)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 0 sot right \n");
|
|
else
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 0 sot error = 0x%x",temp);
|
|
|
|
temp = lt9611_i2c_read_byte(0x9b);
|
|
if(temp == 0xb8)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 1 sot right \n");
|
|
else
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 1 sot error = 0x%x",temp);
|
|
|
|
temp = lt9611_i2c_read_byte(0x9d);
|
|
if(temp == 0xb8)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 2 sot right \n");
|
|
else
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 2 sot error = 0x%x",temp);
|
|
|
|
temp = lt9611_i2c_read_byte(0x9f);
|
|
if(temp == 0xb8)
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 3 sot right \n");
|
|
else
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 3 sot error = 0x%x",temp);
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 0 settle = 0x%x",lt9611_i2c_read_byte(0x98));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 1 settle = 0x%x",lt9611_i2c_read_byte(0x9a));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 2 settle = 0x%x",lt9611_i2c_read_byte(0x9c));
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "port A lane 3 settle = 0x%x",lt9611_i2c_read_byte(0x9e));
|
|
|
|
#endif
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//These function for debug: end
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
|
|
void LT9611_IRQ_Init(void) //dsren
|
|
{
|
|
//int hpd interrupt
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
//lt9611_i2c_write_byte(0x10,0x00); //Output low level active;
|
|
lt9611_i2c_write_byte(0x58,0x0a); //Det HPD 0x0a --> 0x08 20200727
|
|
lt9611_i2c_write_byte(0x59,0x80); //HPD debounce width
|
|
|
|
//intial vid change interrupt
|
|
lt9611_i2c_write_byte(0x9e,0xf7);
|
|
}
|
|
|
|
void LT9611_Globe_Interrupts(bool on)
|
|
{
|
|
if(on)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x81);
|
|
lt9611_i2c_write_byte(0x51,0x10); //hardware mode irq pin out
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x81); //software mode irq pin out = 1;
|
|
lt9611_i2c_write_byte(0x51,0x30);
|
|
}
|
|
|
|
}
|
|
|
|
void LT9611_Enable_Interrupts(CVI_U8 interrupts, bool on)
|
|
{
|
|
if(interrupts == HPD_INTERRUPT_ENABLE)
|
|
{
|
|
if(on)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x07,0xff); //clear3
|
|
lt9611_i2c_write_byte(0x07,0x3f); //clear3
|
|
lt9611_i2c_write_byte(0x03,0x3f); //mask3 //Tx_det
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Enable_Interrupts: hpd_irq_enable\n");
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x07,0xff); //clear3
|
|
lt9611_i2c_write_byte(0x03,0xff); //mask3 //Tx_det
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Enable_Interrupts: hpd_irq_disable\n");
|
|
}
|
|
}
|
|
|
|
if(interrupts == VID_CHG_INTERRUPT_ENABLE)
|
|
{
|
|
if(on)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x9e,0xff); //clear vid chk irq
|
|
lt9611_i2c_write_byte(0x9e,0xf7);
|
|
lt9611_i2c_write_byte(0x04,0xff); //clear0
|
|
lt9611_i2c_write_byte(0x04,0xfe); //clear0
|
|
lt9611_i2c_write_byte(0x00,0xfe); //mask0 vid_chk_IRQ
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Enable_Interrupts: vid_chg_irq_enable\n");
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x04,0xff); //clear0
|
|
lt9611_i2c_write_byte(0x00,0xff); //mask0 vid_chk_IRQ
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Enable_Interrupts: vid_chg_irq_disable\n");
|
|
}
|
|
}
|
|
if(interrupts == CEC_INTERRUPT_ENABLE)
|
|
{
|
|
if(on)
|
|
{
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xfa, 0x00); //cec interrup mask
|
|
lt9611_i2c_write_byte(0xfc, 0x7f); //cec irq clr
|
|
lt9611_i2c_write_byte(0xfc, 0x00);
|
|
|
|
/* cec irq init */
|
|
lt9611_i2c_write_byte(0xff, 0x82);
|
|
lt9611_i2c_write_byte(0x01, 0x7f); //mask bit[7]
|
|
lt9611_i2c_write_byte(0x05, 0xff); //clr bit[7]
|
|
lt9611_i2c_write_byte(0x05, 0x7f);
|
|
}
|
|
else
|
|
{
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xfa, 0xff); //cec interrup mask
|
|
lt9611_i2c_write_byte(0xfc, 0x7f); //cec irq clr
|
|
|
|
/* cec irq init */
|
|
lt9611_i2c_write_byte(0xff, 0x82);
|
|
lt9611_i2c_write_byte(0x01, 0xff); //mask bit[7]
|
|
lt9611_i2c_write_byte(0x05, 0xff); //clr bit[7]
|
|
}
|
|
}
|
|
}
|
|
|
|
void LT9611_HDP_Interrupt_Handle(void)
|
|
{
|
|
Tx_HPD = LT9611_Get_HPD_Status();
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x07,0xff); //clear3
|
|
lt9611_i2c_write_byte(0x07,0x3f); //clear3
|
|
|
|
if(Tx_HPD)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDP_Interrupt_Handle: HDMI connected\n");
|
|
LT9611_LowPower_mode(0);
|
|
LT9611_Enable_Interrupts(VID_CHG_INTERRUPT_ENABLE, 1);
|
|
Timer0_Delay1ms(100);
|
|
LT9611_Read_EDID();
|
|
#ifdef cec_on
|
|
lt9611_parse_physical_address(<9611_cec_msg, Sink_EDID);
|
|
lt9611_cec_la_allocation(<9611_cec_msg);
|
|
#endif
|
|
|
|
LT9611_Video_Check();
|
|
if(Video_Format != video_none)
|
|
{
|
|
LT9611_PLL(video);
|
|
LT9611_MIPI_Pcr(video);
|
|
LT9611_HDMI_TX_Digital(video);
|
|
LT9611_HDMI_Out_Enable();
|
|
}
|
|
else
|
|
{
|
|
LT9611_HDMI_Out_Disable();
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDP_Interrupt_Handle: no mipi video, disable hdmi output\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_HDP_Interrupt_Handle: HDMI disconnected\n");
|
|
LT9611_Enable_Interrupts(VID_CHG_INTERRUPT_ENABLE, 0);
|
|
//LT9611_LowPower_mode(1);
|
|
#ifdef cec_on
|
|
lt9611_cec_msg_init(<9611_cec_msg);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void LT9611_Vid_Chg_Interrupt_Handle(void)
|
|
{
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Vid_Chg_Interrupt_Handle: \n");
|
|
#if 1
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x9e,0xff); //clear vid chk irq
|
|
lt9611_i2c_write_byte(0x9e,0xf7);
|
|
|
|
lt9611_i2c_write_byte(0x04,0xff); //clear0 irq
|
|
lt9611_i2c_write_byte(0x04,0xfe);
|
|
#endif
|
|
//Timer0_Delay1ms(100);
|
|
LT9611_Video_Check();
|
|
|
|
if(Video_Format != video_none)
|
|
{
|
|
LT9611_PLL(video);
|
|
LT9611_MIPI_Pcr(video);
|
|
LT9611_HDMI_TX_Digital(video);
|
|
LT9611_HDMI_Out_Enable();
|
|
//LT9611_HDCP_Enable();
|
|
}
|
|
else
|
|
{
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_Vid_Chg_Interrupt_Handle: no mipi video\n");
|
|
LT9611_HDMI_Out_Disable();
|
|
}
|
|
}
|
|
|
|
void lt9611_cec_msg_Interrupt_Handle(struct cec_msg *cec_msg)
|
|
{
|
|
CVI_U8 cec_status;
|
|
|
|
lt9611_i2c_write_byte(0xff,0x86);
|
|
cec_status = lt9611_i2c_read_byte(0xd2) ;
|
|
|
|
cec_msg->cec_status = cec_status;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "IRQ cec_status: 0x%x",cec_status);
|
|
|
|
lt9611_i2c_write_byte(0xff, 0x86);
|
|
lt9611_i2c_write_byte(0xfc, 0x7f); //cec irq clr
|
|
lt9611_i2c_write_byte(0xfc, 0x00);
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x05,0xff); //clear3
|
|
lt9611_i2c_write_byte(0x05,0x7f); //clear3
|
|
|
|
lt9611_cec_msg_tx_handle(cec_msg);
|
|
lt9611_cec_msg_rx_parse(cec_msg);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//These function for Pattern output: start
|
|
/////////////////////////////////////////////////////////////
|
|
void LT9611_pattern_gcm(struct video_timing *video_format)
|
|
{
|
|
CVI_U8 POL;
|
|
POL = (video_format-> h_polarity)*0x10 + (video_format-> v_polarity)*0x20;
|
|
POL = ~POL;
|
|
POL &= 0x30;
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0xa3,(CVI_U8)((video_format->hs+video_format->hbp)/256));//de_delay
|
|
lt9611_i2c_write_byte(0xa4,(CVI_U8)((video_format->hs+video_format->hbp)%256));
|
|
lt9611_i2c_write_byte(0xa5,(CVI_U8)((video_format->vs+video_format->vbp)%256));//de_top
|
|
lt9611_i2c_write_byte(0xa6,(CVI_U8)(video_format->hact/256));
|
|
lt9611_i2c_write_byte(0xa7,(CVI_U8)(video_format->hact%256)); //de_cnt
|
|
lt9611_i2c_write_byte(0xa8,(CVI_U8)(video_format->vact/256));
|
|
lt9611_i2c_write_byte(0xa9,(CVI_U8)(video_format->vact%256)); //de_line
|
|
lt9611_i2c_write_byte(0xaa,(CVI_U8)(video_format->htotal/256));
|
|
lt9611_i2c_write_byte(0xab,(CVI_U8)(video_format->htotal%256));//htotal
|
|
lt9611_i2c_write_byte(0xac,(CVI_U8)(video_format->vtotal/256));
|
|
lt9611_i2c_write_byte(0xad,(CVI_U8)(video_format->vtotal%256));//vtotal
|
|
lt9611_i2c_write_byte(0xae,(CVI_U8)(video_format->hs/256));
|
|
lt9611_i2c_write_byte(0xaf,(CVI_U8)(video_format->hs%256)); //hvsa
|
|
lt9611_i2c_write_byte(0xb0,(CVI_U8)(video_format->vs%256)); //vsa
|
|
|
|
lt9611_i2c_write_byte(0x47,(CVI_U8)(POL|0x07)); //sync polarity
|
|
|
|
}
|
|
|
|
void LT9611_pattern_pixel_clk(struct video_timing *video_format)
|
|
{
|
|
CVI_U32 pclk;
|
|
pclk = video_format->pclk_khz;
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "set pixel clk = %d", pclk);
|
|
//printdec_u32(pclk); //Dec
|
|
|
|
lt9611_i2c_write_byte(0xff,0x83);
|
|
lt9611_i2c_write_byte(0x2d,0x50);
|
|
|
|
if(pclk == 297000)
|
|
{
|
|
lt9611_i2c_write_byte(0x26,0xb6);
|
|
lt9611_i2c_write_byte(0x27,0xf0);
|
|
}
|
|
if(pclk == 148500)
|
|
{
|
|
lt9611_i2c_write_byte(0x26,0xb7);
|
|
}
|
|
if(pclk == 74250)
|
|
{
|
|
lt9611_i2c_write_byte(0x26,0x9c);
|
|
}
|
|
lt9611_i2c_write_byte(0xff,0x80);
|
|
lt9611_i2c_write_byte(0x11,0x5a); //Pcr reset
|
|
lt9611_i2c_write_byte(0x11,0xfa);
|
|
}
|
|
|
|
void LT9611_pattern_en(void)
|
|
{
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0x4f,0x80); //[7] = Select ad_txpll_d_clk.
|
|
lt9611_i2c_write_byte(0x50,0x20);
|
|
}
|
|
|
|
void LT9611_pattern(void)
|
|
{
|
|
//DTV
|
|
//video = &video_640x480_60Hz;
|
|
//video = &video_720x480_60Hz;
|
|
//video = &video_1280x720_60Hz;
|
|
video = &video_1920x1080_60Hz;
|
|
//video = &video_3840x2160_30Hz;
|
|
|
|
//DMT
|
|
//video = &video_1024x600_60Hz;
|
|
//video = &video_1024x600_60Hz;
|
|
//video = &video_1280x800_60Hz;
|
|
|
|
//video = &video_1920x1080_30Hz;
|
|
|
|
LT9611_Chip_ID();
|
|
LT9611_System_Init();
|
|
LT9611_pattern_en();
|
|
LT9611_PLL(video);
|
|
LT9611_pattern_gcm(video);
|
|
|
|
LT9611_HDMI_TX_Digital(video);
|
|
LT9611_HDMI_TX_Phy();
|
|
|
|
LT9611_Pcr_MK_Print();
|
|
|
|
#if 0
|
|
//Audio pattern
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
lt9611_i2c_write_byte(0xd6,0x8c);
|
|
lt9611_i2c_write_byte(0xd7,0x06); //sync polarity
|
|
|
|
lt9611_i2c_write_byte(0xff,0x84);
|
|
lt9611_i2c_write_byte(0x06,0x0c);
|
|
lt9611_i2c_write_byte(0x07,0x10);
|
|
lt9611_i2c_write_byte(0x16,0x01);
|
|
|
|
lt9611_i2c_write_byte(0x34,0xd4); //CTS_N
|
|
#endif
|
|
LT9611_Audio_Init();
|
|
LT9611_HDCP_Init();
|
|
LT9611_load_hdcp_key();
|
|
|
|
//LT9611_Read_EDID();
|
|
LT9611_HDMI_Out_Enable();
|
|
//LT9611_HDMI_CEC_ON(1);
|
|
//lt9611_cec_msg_set_logical_address();
|
|
|
|
//while(1)
|
|
//{
|
|
// lt9611_cec_msg_write_demo();
|
|
//}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//These function for debug: end
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
|
|
void LT9611_Init(void)
|
|
{
|
|
LT9611_Chip_ID();
|
|
LT9611_System_Init();
|
|
|
|
LT9611_MIPI_Input_Analog();
|
|
LT9611_MIPI_Input_Digtal();
|
|
|
|
Timer0_Delay1ms(1000);
|
|
LT9611_Video_Check();
|
|
|
|
LT9611_PLL(video);
|
|
LT9611_MIPI_Pcr(video);
|
|
|
|
LT9611_Audio_Init();
|
|
LT9611_CSC();
|
|
LT9611_HDCP_Init();
|
|
LT9611_HDMI_TX_Digital(video);
|
|
LT9611_HDMI_TX_Phy();
|
|
|
|
LT9611_IRQ_Init();;
|
|
lt9611_cec_msg_init(<9611_cec_msg);
|
|
|
|
LT9611_Enable_Interrupts(HPD_INTERRUPT_ENABLE, 1);
|
|
LT9611_Enable_Interrupts(VID_CHG_INTERRUPT_ENABLE, 0);
|
|
LT9611_Enable_Interrupts(CEC_INTERRUPT_ENABLE, 1);
|
|
|
|
LT9611_Frequency_Meter_Byte_Clk();
|
|
LT9611_Dphy_debug();
|
|
LT9611_Htotal_Sysclk();
|
|
LT9611_Pcr_MK_Print();
|
|
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "==========================LT9611 Initial End===============================\n");
|
|
Timer0_Delay1ms(200); //HPD have debounce, wait HPD irq.
|
|
LT9611_HDP_Interrupt_Handle();
|
|
}
|
|
|
|
void LT9611_IRQ_Task(void)
|
|
{
|
|
CVI_U8 irq_flag3;
|
|
CVI_U8 irq_flag0;
|
|
CVI_U8 irq_flag1;
|
|
|
|
//CVI_TRACE_LOG(CVI_DBG_INFO, "LT9611_IRQ_Task :IRQ Task\n");
|
|
|
|
lt9611_i2c_write_byte(0xff,0x82);
|
|
|
|
irq_flag0=lt9611_i2c_read_byte(0x0c);
|
|
irq_flag1=lt9611_i2c_read_byte(0x0d);
|
|
irq_flag3=lt9611_i2c_read_byte(0x0f);
|
|
|
|
if((irq_flag1&0x80) == 0x80)
|
|
{
|
|
lt9611_cec_msg_Interrupt_Handle(<9611_cec_msg);
|
|
}
|
|
|
|
if(irq_flag3&0xc0) //HPD interrupt
|
|
{
|
|
LT9611_HDP_Interrupt_Handle();
|
|
}
|
|
|
|
if(irq_flag0&0x01) //vid_chk
|
|
{
|
|
LT9611_Vid_Chg_Interrupt_Handle();
|
|
}
|
|
}
|
|
|
|
static void __upadte_video(LT9611_VIDEO_FORMAT_E enVideoFormat)
|
|
{
|
|
switch(enVideoFormat)
|
|
{
|
|
case E_LT9611_VIDEO_1024x768_60HZ:
|
|
Video_Format = video_other;
|
|
video = &video_1024x768_60Hz;
|
|
break;
|
|
case E_LT9611_VIDEO_1280x720_60HZ:
|
|
Video_Format = video_1280x720_60Hz_vic4;
|
|
video = &video_1280x720_60Hz;
|
|
break;
|
|
case E_LT9611_VIDEO_1280x1024_60HZ:
|
|
Video_Format = video_other;
|
|
video = &video_1280x1024_60Hz;
|
|
break;
|
|
case E_LT9611_VIDEO_1600x1200_60HZ:
|
|
Video_Format = video_other;
|
|
video = &video_1600x1200_60Hz;
|
|
break;
|
|
case E_LT9611_VIDEO_1920x1080_30HZ:
|
|
Video_Format=video_1920x1080_30Hz_vic;
|
|
video = &video_1920x1080_30Hz;
|
|
break;
|
|
case E_LT9611_VIDEO_1920x1080_60HZ:
|
|
Video_Format = video_1920x1080_60Hz_vic16;
|
|
video = &video_1920x1080_60Hz;
|
|
break;
|
|
default:
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "ERROR: unknown video format...\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void lt9611_init(LT9611_VIDEO_FORMAT_E enVideoFormat)
|
|
{
|
|
LT9611_init_i2c();
|
|
LT9611_Chip_ID();
|
|
LT9611_System_Init();
|
|
|
|
LT9611_MIPI_Input_Analog();
|
|
LT9611_MIPI_Input_Digtal();
|
|
|
|
__upadte_video(enVideoFormat);
|
|
|
|
LT9611_PLL(video);
|
|
LT9611_MIPI_Pcr(video);
|
|
|
|
LT9611_Audio_Init();
|
|
|
|
LT9611_HDCP_Init();
|
|
LT9611_HDMI_TX_Digital(video);
|
|
LT9611_HDMI_TX_Phy();
|
|
LT9611_HDMI_Out_Enable();
|
|
}
|
|
|
|
void lt9611_set_video_format(LT9611_VIDEO_FORMAT_E enVideoFormat)
|
|
{
|
|
__upadte_video(enVideoFormat);
|
|
LT9611_HDMI_Out_Disable();
|
|
|
|
usleep(1000000);
|
|
|
|
LT9611_PLL(video);
|
|
LT9611_MIPI_Pcr(video);
|
|
LT9611_HDMI_TX_Digital(video);
|
|
|
|
LT9611_HDMI_Out_Enable();
|
|
}
|
|
|
|
|
|
CVI_S32 lt9611_get_video_format(char* pinput_str)
|
|
{
|
|
CVI_S32 i = 0;
|
|
bool is_find = false;
|
|
for(int i=0;i<E_LT9611_VIDEO_MAX;i++)
|
|
{
|
|
if(strcmp(pinput_str, s_hdmi_resolution_arr[i]) == 0)
|
|
{
|
|
is_find = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!is_find)
|
|
{
|
|
return CVI_FAILURE;
|
|
}
|
|
g_video_format = (LT9611_VIDEO_FORMAT_E)i;
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
void printHdmiHelp(char **argv)
|
|
{
|
|
CVI_U32 idx;
|
|
|
|
printf("// ------------------------------------------------\n");
|
|
printf("%s --resolution=select hdmi display solution\n", argv[0]);
|
|
printf("\noptional resolution list by lt9611:\n");
|
|
for(CVI_S32 i=0;i<E_LT9611_VIDEO_MAX;i++)
|
|
{
|
|
printf(" %s\n", s_hdmi_resolution_arr[i]);
|
|
}
|
|
printf("\nEX.\n");
|
|
printf(" %s -h\n", argv[0]);
|
|
printf(" %s --resolution=1920x1080_30HZ\n", argv[0]);
|
|
printf(" %s -d\n", argv[0]);
|
|
printf("// ------------------------------------------------\n");
|
|
|
|
for (idx = 0; idx < sizeof(long_option_ext) / sizeof(optionExt); idx++) {
|
|
if (long_option_ext[idx].opt.name == NULL)
|
|
break;
|
|
|
|
printf("--%s\n", long_option_ext[idx].opt.name);
|
|
printf(" %s\n", long_option_ext[idx].help);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if(argc == 1) {
|
|
lt9611_init(g_video_format);
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
struct option long_options[MAX_CMD_OPTIONS + 1];
|
|
CVI_S32 ch, idx, ret;
|
|
|
|
memset((void *)long_options, 0, sizeof(long_options));
|
|
|
|
for (idx = 0; idx < MAX_CMD_OPTIONS; idx++) {
|
|
if (long_option_ext[idx].opt.name == NULL)
|
|
break;
|
|
|
|
if (idx >= MAX_CMD_OPTIONS) {
|
|
CVI_TRACE_LOG(CVI_DBG_ERR, "too many options\n");
|
|
return -1;
|
|
}
|
|
|
|
memcpy(&long_options[idx], &long_option_ext[idx].opt, sizeof(struct option));
|
|
}
|
|
|
|
optind = 0;
|
|
while ((ch = getopt_long(argc, argv, "h", long_options, &idx)) != -1) {
|
|
switch (ch) {
|
|
case 'r':
|
|
ret = lt9611_get_video_format(optarg);
|
|
if(ret != CVI_SUCCESS) {
|
|
CVI_TRACE_LOG(CVI_DBG_ERR, "invalid resolution parameter\n");
|
|
return ret;
|
|
}
|
|
break;
|
|
case 'h':
|
|
printHdmiHelp(argv);
|
|
return CVI_SUCCESS;
|
|
default:
|
|
CVI_TRACE_LOG(CVI_DBG_INFO, "ch = %c\n", ch);
|
|
printHdmiHelp(argv);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(optind < argc){
|
|
printHdmiHelp(argv);
|
|
}
|
|
|
|
lt9611_init(g_video_format);
|
|
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
|
|
|