458 lines
10 KiB
C
458 lines
10 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* it66353 HDMI 3 in 1 out driver.
|
|
*
|
|
* Author: Kenneth.Hung@ite.com.tw
|
|
* Wangqiang Guo <kay.guo@rock-chips.com>
|
|
* Version: IT66353_SAMPLE_1.08
|
|
*
|
|
*/
|
|
#ifndef _IT66353_DRV_H_
|
|
#define _IT66353_DRV_H_
|
|
|
|
#include "platform.h"
|
|
#include "it66353.h"
|
|
|
|
#define RX_PORT_0 0
|
|
#define RX_PORT_1 1
|
|
#define RX_PORT_2 2
|
|
#define RX_PORT_3 3
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
#define DDCWAITTIME 5
|
|
#define DDCWAITNUM 10
|
|
|
|
#define RX_PORT_COUNT 4
|
|
|
|
// for it66353_rx_term_power_down
|
|
#define CH0_OFF (0x10)
|
|
#define CH1_OFF (0x20)
|
|
#define CH2_OFF (0x40)
|
|
#define CLK_OFF (0x80)
|
|
#define ALLCH_OFF (0xF0)
|
|
#define ALLCH_ON (0x00)
|
|
|
|
/* ===================================================
|
|
* config:
|
|
* ===================================================
|
|
*
|
|
* RCLKFreqSel => 0: 20MHz, 1: 10MHz, 2: 5MHz, 3: 2.5MHz
|
|
*/
|
|
#define RCLKFreqSel 0
|
|
|
|
typedef enum {
|
|
RX_TOGGLE_HPD,
|
|
RX_PORT_CHANGE,
|
|
TX_OUTPUT,
|
|
TX_OUTPUT_PREPARE,
|
|
RX_CHECK_EQ,
|
|
SETUP_AFE,
|
|
RX_WAIT_CLOCK,
|
|
RX_HPD,
|
|
TX_GOT_HPD,
|
|
TX_WAIT_HPD,
|
|
TX_UNPLUG,
|
|
RX_UNPLUG,
|
|
IDLE,
|
|
} _SYS_FSM_STATE;
|
|
|
|
enum {
|
|
HDMI_MODE_AUTO,
|
|
HDMI_MODE_14,
|
|
HDMI_MODE_20,
|
|
};
|
|
|
|
enum {
|
|
EQ_MODE_H14,
|
|
EQ_MODE_H20,
|
|
};
|
|
|
|
|
|
typedef enum {
|
|
DEV_DEVICE_LOOP,
|
|
DEV_DEVICE_INIT,
|
|
DEV_WAIT_DEVICE_READY,
|
|
DEV_FW_VAR_INIT,
|
|
DEV_WAIT_RESET,
|
|
} _DEV_FSM_STATE;
|
|
|
|
typedef enum {
|
|
AEQ_OFF,
|
|
AEQ_START,
|
|
AEQ_CHECK_SAREQ_RESULT,
|
|
AEQ_APPLY_SAREQ,
|
|
AEQ_DONE,
|
|
AEQ_FAIL,
|
|
AEQ_MAX,
|
|
} _AEQ_FSM_STATE;
|
|
|
|
typedef enum {
|
|
EQRES_UNKNOWN,
|
|
EQRES_BUSY,
|
|
EQRES_SAREQ_DONE,
|
|
EQRES_SAREQ_FAIL,
|
|
EQRES_SAREQ_TIMEOUT,
|
|
EQRES_H14EQ_DONE,
|
|
EQRES_H14EQ_FAIL,
|
|
EQRES_H14EQ_TIMEOUT,
|
|
EQRES_DONE,
|
|
} _EQ_RESULT_TYPE;
|
|
|
|
typedef enum {
|
|
SysAEQ_OFF,
|
|
SysAEQ_RUN,
|
|
SysAEQ_DONE,
|
|
} _SYS_AEQ_TYPE;
|
|
|
|
enum {
|
|
EDID_SRC_EXT_SINK,
|
|
EDID_SRC_INTERNAL,
|
|
};
|
|
|
|
enum {
|
|
TERM_LOW,
|
|
TERM_HIGH,
|
|
TERM_FOLLOW_TX,
|
|
TERM_FOLLOW_HPD,
|
|
};
|
|
|
|
#define EDID_PORT_0 0x01
|
|
#define EDID_PORT_1 0x02
|
|
#define EDID_PORT_2 0x04
|
|
#define EDID_PORT_3 0x08
|
|
#define EDID_PORT_ALL (EDID_PORT_0 | EDID_PORT_1 | EDID_PORT_2 | EDID_PORT_3)
|
|
|
|
/*
|
|
* for it66353_get_port_info0()
|
|
*/
|
|
#define PI_5V (BIT(0))
|
|
#define PI_HDMI_MODE (BIT(1))
|
|
#define PI_CLK_DET (BIT(2))
|
|
#define PI_CLK_VALID (BIT(3))
|
|
#define PI_CLK_STABLE (BIT(4))
|
|
#define PI_PLL_LOCK (BIT(5))
|
|
// #define PI_XX (BIT(6))
|
|
#define PI_SYM_LOCK (BIT(7))
|
|
|
|
/*
|
|
* for it66353_get_port_info1()
|
|
*/
|
|
#define PI_PLL_HS1G 0x01
|
|
// #define PI_PLL_HS1G (BIT0)
|
|
|
|
typedef struct {
|
|
// TxSwap
|
|
u8 EnTxPNSwap;
|
|
u8 EnTxChSwap;
|
|
u8 EnTxVCLKInv;
|
|
u8 EnTxOutD1t;
|
|
|
|
u8 EnRxDDCBypass;
|
|
u8 EnRxPWR5VBypass;
|
|
u8 EnRxHPDBypass;
|
|
|
|
u8 EnCEC;
|
|
|
|
u8 EnableAutoEQ;
|
|
u8 ParseEDIDFromSink;
|
|
u8 NonActivePortReplyHPD;
|
|
u8 DisableEdidRam;
|
|
u8 TryFixedEQFirst;
|
|
u8 TurnOffTx5VWhenSwitchPort;
|
|
u8 FixIncorrectHdmiEnc;
|
|
|
|
} IT6635_DEVICE_OPTION_INT;
|
|
|
|
typedef struct {
|
|
u8 tag1;
|
|
u8 EnRxDDCBypass;
|
|
u8 EnRxPWR5VBypass;
|
|
u8 EnRxHPDBypass;
|
|
u8 TryFixedEQFirst;
|
|
u8 EnableAutoEQ;
|
|
u8 NonActivePortReplyHPD;
|
|
u8 DisableEdidRam;
|
|
u8 DefaultEQ[3];
|
|
u8 FixIncorrectHdmiEnc;
|
|
u8 HPDOutputInverse;
|
|
u8 HPDTogglePeriod;
|
|
u8 TxOEAlignment;
|
|
u8 str_size;
|
|
|
|
} IT6635_RX_OPTIONS;
|
|
|
|
typedef struct {
|
|
u8 tag1;
|
|
// TxSwap
|
|
u8 EnTxPNSwap;
|
|
u8 EnTxChSwap;
|
|
u8 EnTxVCLKInv;
|
|
u8 EnTxOutD1t;
|
|
u8 CopyEDIDFromSink;
|
|
u8 ParsePhysicalAddr;
|
|
u8 TurnOffTx5VWhenSwitchPort;
|
|
u8 str_size;
|
|
|
|
} IT6635_TX_OPTIONS;
|
|
|
|
typedef struct {
|
|
u8 tag1;
|
|
u8 SwAddr;
|
|
u8 RxAddr;
|
|
u8 CecAddr;
|
|
u8 EdidAddr;
|
|
u8 ForceRxOn;
|
|
u8 RxAutoPowerDown;
|
|
u8 DoTxPowerDown;
|
|
u8 TxPowerDownWhileWaitingClock;
|
|
u8 str_size;
|
|
|
|
} IT6635_DEV_OPTION;
|
|
|
|
typedef struct {
|
|
IT6635_RX_OPTIONS *active_rx_opt;
|
|
IT6635_RX_OPTIONS *rx_opt[4];
|
|
IT6635_TX_OPTIONS *tx_opt;
|
|
IT6635_DEV_OPTION *dev_opt;
|
|
|
|
} IT6635_DEV_OPTION_INTERNAL;
|
|
|
|
typedef struct {
|
|
struct {
|
|
u8 Rev;
|
|
u32 RCLK;
|
|
u8 RxHPDFlag[4];
|
|
|
|
u8 VSDBOffset; // 0xFF;
|
|
|
|
u8 PhyAdr[4];
|
|
u8 EdidChkSum[2];
|
|
|
|
_SYS_FSM_STATE state_sys_fsm;
|
|
u8 state_dev_init;
|
|
u8 state_dev;
|
|
u8 fsm_return;
|
|
u8 Rx_active_port;
|
|
u8 Rx_new_port;
|
|
u8 Tx_current_5v;
|
|
u32 vclk;
|
|
u32 vclk_prev;
|
|
|
|
u16 RxCEDErr[3];
|
|
u8 RxCEDErrValid;
|
|
u16 RxCEDErrRec[3][3];
|
|
|
|
u8 count_unlock;
|
|
u8 count_symlock;
|
|
u8 count_symlock_lost;
|
|
u8 count_symlock_fail;
|
|
u8 count_symlock_unstable;
|
|
u8 count_fsm_err;
|
|
u8 count_eq_check;
|
|
u8 count_try_force_hdmi_mode;
|
|
u8 count_auto_eq_fail;
|
|
u8 count_wait_clock;
|
|
u8 clock_ratio;
|
|
u8 h2_scramble;
|
|
u8 edid_ready;
|
|
u8 prev_hpd_state;
|
|
|
|
u8 try_fixed_EQ;
|
|
u8 current_hdmi_mode;
|
|
u8 current_txoe;
|
|
u8 check_for_hpd_toggle;
|
|
u8 sdi_stable_count;
|
|
u8 check_for_sdi;
|
|
u8 force_hpd_state;
|
|
// u8 txoe_alignment;
|
|
u8 hpd_toggle_timeout;
|
|
u8 spmon;
|
|
|
|
__tick tick_set_afe;
|
|
__tick tick_hdcp;
|
|
// u8 en_count_hdcp;
|
|
u8 *default_edid[4];
|
|
|
|
// tx
|
|
u8 hpd_wait_count;
|
|
u8 is_hdmi20_sink;
|
|
u8 rx_deskew_err;
|
|
} vars;
|
|
|
|
struct {
|
|
_SYS_AEQ_TYPE sys_aEQ;
|
|
u8 AutoEQ_state;
|
|
u8 AutoEQ_WaitTime;
|
|
u8 AutoEQ_Result;
|
|
u8 DFE_Valid;
|
|
u8 RS_Valid;
|
|
u16 RS_ValidMap[3];
|
|
u8 EqHDMIMode;
|
|
u8 ManuEQ_state;
|
|
u8 DFE[14][3][3]; // [RS_value][channel012][NumABC] -> 0x34B...0x353
|
|
u8 CalcRS[3];
|
|
|
|
u8 EQ_flag_14;
|
|
u8 EQ_flag_20;
|
|
u8 txoe_ready14;
|
|
u8 txoe_ready20;
|
|
u8 stored_RS_14[3];
|
|
u8 stored_RS_20[3];
|
|
u8 current_eq_mode;
|
|
|
|
// u8 FixedRsIndex[4];
|
|
|
|
u8 meq_cur_idx;
|
|
|
|
u8 meq_adj_idx[3];
|
|
u32 ced_err_avg[3];
|
|
u32 ced_err_avg_prev[3];
|
|
u8 ced_acc_count;
|
|
u8 manu_eq_fine_tune_count[3];
|
|
u8 manu_eq_fine_tune_best_rs[3];
|
|
|
|
} EQ;
|
|
|
|
// u8 edid_buf[128];
|
|
|
|
IT6635_DEV_OPTION_INTERNAL opts;
|
|
|
|
} IT6635_DEVICE_DATA;
|
|
|
|
extern IT6635_DEVICE_DATA it66353_gdev;
|
|
extern const u8 it66353_rs_value[];
|
|
extern IT6635_RX_OPTIONS it66353_s_RxOpts;
|
|
extern IT6635_TX_OPTIONS it66353_s_TxOpts;
|
|
extern IT6635_DEV_OPTION it66353_s_DevOpts;
|
|
extern u8 it66353_s_default_edid_port0[];
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
// --------------------------------
|
|
extern u8 it66353_h2swwr(u8 offset, u8 wdata);
|
|
extern u8 it66353_h2swrd(u8 offset);
|
|
extern u8 it66353_h2swset(u8 offset, u8 mask, u8 wdata);
|
|
extern void it66353_h2swbrd(u8 offset, u8 length, u8 *rddata);
|
|
extern void it66353_h2swbwr(u8 offset, u8 length, u8 *rddata);
|
|
|
|
extern u8 it66353_h2rxwr(u8 offset, u8 wdata);
|
|
extern u8 it66353_h2rxrd(u8 offset);
|
|
extern u8 it66353_h2rxset(u8 offset, u8 mask, u8 dwata);
|
|
extern void it66353_h2rxbrd(u8 offset, u8 length, u8 *rddata);
|
|
extern void it66353_h2rxbwr(u8 offset, u8 length, u8 *rddata);
|
|
|
|
extern u8 it66353_cecwr(u8 offset, u8 wdata);
|
|
extern u8 it66353_cecrd(u8 offset);
|
|
extern u8 it66353_cecset(u8 offset, u8 mask, u8 wdata);
|
|
extern void it66353_cecbrd(u8 offset, u8 length, u8 *rddata);
|
|
extern void it66353_cecbwr(u8 offset, u8 length, u8 *rddata);
|
|
|
|
extern u8 it66353_h2rxedidwr(u8 offset, u8 *wrdata, u8 length);
|
|
|
|
extern void it66353_chgrxbank(u8 bankno);
|
|
extern void it66353_chgswbank(u8 bankno);
|
|
|
|
extern void it66353_rx_update_ced_err_from_hw(void);
|
|
extern void it66353_rx_get_ced_err(void);
|
|
extern void it66353_rx_clear_ced_err(void);
|
|
extern u8 it66353_rx_monitor_ced_err(void);
|
|
extern void it66353_rx_DFE_enable(u8 enable);
|
|
extern void it66353_rx_set_rs_3ch(u8 *rs_value);
|
|
extern void it66353_rx_set_rs(u8 ch, u8 rs_value);
|
|
|
|
extern u8 it66353_rx_is_all_ch_symlock(void);
|
|
extern u8 it66353_rx_is_ch_symlock(u8 ch);
|
|
extern u8 it66353_rx_is_clock_stable(void);
|
|
|
|
extern void it66353_rx_ovwr_hdmi_clk(u8 port, u8 ratio);
|
|
extern void it66353_rx_ovwr_h20_scrb(u8 port, u8 scrb);
|
|
|
|
extern void it66353_rx_auto_power_down_enable(u8 port, u8 enable);
|
|
extern void it66353_rx_term_power_down(u8 port, u8 channel);
|
|
extern void it66353_rx_handle_output_err(void);
|
|
|
|
extern void it66353_sw_enable_timer0(void);
|
|
extern void it66353_sw_disable_timer0(void);
|
|
extern u8 it66353_sw_get_timer0_interrupt(void);
|
|
|
|
extern void it66353_sw_clear_hdcp_status(void);
|
|
// --------------------------------
|
|
extern void it66353_txoe(u8 enable);
|
|
extern void it66353_auto_detect_hdmi_encoding(void);
|
|
extern void it66353_fix_incorrect_hdmi_encoding(void);
|
|
|
|
extern u8 it66353_get_port_info1(u8 port, u8 info);
|
|
extern u8 it66353_get_port_info0(u8 port, u8 info);
|
|
|
|
extern void it66353_init_rclk(void);
|
|
extern void it66353_enable_tx_port(u8 enable);
|
|
// --------------
|
|
extern void it66353_sys_state(u8 new_state);
|
|
extern void it66353_rx_reset(void);
|
|
extern void it66353_rx_caof_init(u8 port);
|
|
|
|
extern void it66353_eq_save_h20(void);
|
|
extern void it66353_eq_load_h20(void);
|
|
extern void it66353_eq_save_h14(void);
|
|
extern void it66353_eq_load_h14(void);
|
|
extern void it66353_eq_load_previous(void);
|
|
extern void it66353_eq_load_default(void);
|
|
|
|
extern void it66353_eq_reset_state(void);
|
|
extern void it66353_eq_set_state(u8 state);
|
|
extern u8 it66353_eq_get_state(void);
|
|
extern void it66353_eq_reset_txoe_ready(void);
|
|
extern void it66353_eq_set_txoe_ready(u8 ready);
|
|
extern u8 it66353_eq_get_txoe_ready(void);
|
|
|
|
extern void it66353_aeq_set_DFE2(u8 EQ0, u8 EQ1, u8 EQ2);
|
|
extern u8 it66353_rx_is_hdmi20(void);
|
|
extern void it66353_aeq_diable_eq_trigger(void);
|
|
extern u8 it66353_aeq_check_sareq_result(void);
|
|
|
|
#if DEBUG_FSM_CHANGE
|
|
#define it66353_fsm_chg(new_state) __it66353_fsm_chg(new_state, __LINE__)
|
|
#define it66353_fsm_chg_delayed(new_state) __it66353_fsm_chg2(new_state, __LINE__)
|
|
#else
|
|
extern void it66353_fsm_chg(u8 new_state);
|
|
extern void it66353_fsm_chg_delayed(u8 new_state);
|
|
#endif
|
|
|
|
extern void __it66353_fsm_chg(u8 new_state, int caller);
|
|
extern void __it66353_fsm_chg2(u8 new_state, int caller);
|
|
// void it66353_vars_init(void);
|
|
extern bool it66353_device_init(void);
|
|
extern bool it66353_device_init2(void);
|
|
|
|
extern bool it66353_read_edid(u8 block, u8 offset, int length, u8 *edid_buffer);
|
|
extern bool it66353_write_one_block_edid(u8 block, u8 *edid_buffer);
|
|
extern bool it66353_setup_edid_ram(u8 flag);
|
|
|
|
extern void it66353_force_hdmi20(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
extern void it66353_rx_skew_adj(u8 ch);
|
|
#define _rx_edid_address_enable(port)\
|
|
{it66353_h2swset(0x55 + port, 0x24, 0x20); }
|
|
#define _rx_edid_address_disable(port)\
|
|
{it66353_h2swset(0x55 + port, 0x24, 0x04); }
|
|
#define _rx_edid_ram_enable(port)\
|
|
{if (it66353_gdev.opts.rx_opt[port]->EnRxDDCBypass == 0) { it66353_h2swset(0x55 + port, 0x01, 0x00); }}
|
|
#define _rx_edid_ram_disable(port)\
|
|
{ it66353_h2swset(0x55 + port, 0x01, 0x01); }
|
|
#define _rx_edid_set_chksum(port, sum)\
|
|
{ it66353_h2swwr(0xe1 + port * 2, sum); }
|
|
#define _rx_edid_set_cec_phyaddr(port, phyAB, phyCD)\
|
|
{ it66353_h2swwr(0xd9 + port*2, phyAB); it66353_h2swwr(0xda + port*2, phyCD); }
|
|
|
|
#endif |