mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
media: i2c: it66353: add it66353 HDMI switch bridge driver
Signed-off-by: Wangqiang Guo <kay.guo@rock-chips.com> Change-Id: I4365641c2d088a5bce4c0b69ed98b864831db9d5
This commit is contained in:
@@ -594,6 +594,7 @@ config VIDEO_SAA717X
|
||||
module will be called saa717x.
|
||||
|
||||
source "drivers/media/i2c/cx25840/Kconfig"
|
||||
source "drivers/media/i2c/it66353/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
|
||||
obj-$(CONFIG_VIDEO_SMIAPP) += smiapp/
|
||||
obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
|
||||
obj-$(CONFIG_VIDEO_CX25840) += cx25840/
|
||||
obj-$(CONFIG_VIDEO_IT66353) += it66353/
|
||||
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
|
||||
obj-$(CONFIG_VIDEO_NVP6158) += nvp6158_drv/
|
||||
obj-$(CONFIG_VIDEO_NVP6188) += nvp6188.o
|
||||
|
||||
73
drivers/media/i2c/it66353/IT66353_drv_h_str.h
Normal file
73
drivers/media/i2c/it66353/IT66353_drv_h_str.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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
|
||||
*
|
||||
*/
|
||||
#ifdef __init_str_SYS_FSM_STATE
|
||||
static char *s__SYS_FSM_STATE[] = {
|
||||
"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",
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef __init_str_DEV_FSM_STATE
|
||||
static char *s__DEV_FSM_STATE[] = {
|
||||
"DEV_DEVICE_LOOP",
|
||||
"DEV_DEVICE_INIT",
|
||||
"DEV_WAIT_DEVICE_READY",
|
||||
"DEV_FW_VAR_INIT",
|
||||
"DEV_WAIT_RESET",
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef __init_str_AEQ_FSM_STATE
|
||||
static char *s__AEQ_FSM_STATE[] = {
|
||||
"AEQ_OFF",
|
||||
"AEQ_START",
|
||||
"AEQ_CHECK_SAREQ_RESULT",
|
||||
"AEQ_APPLY_SAREQ",
|
||||
"AEQ_DONE",
|
||||
"AEQ_FAIL",
|
||||
"AEQ_MAX",
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef __init_str_EQ_RESULT_TYPE
|
||||
static char *s__EQ_RESULT_TYPE[] = {
|
||||
"EQRES_UNKNOWN",
|
||||
"EQRES_BUSY",
|
||||
"EQRES_SAREQ_DONE",
|
||||
"EQRES_SAREQ_FAIL",
|
||||
"EQRES_SAREQ_TIMEOUT",
|
||||
"EQRES_H14EQ_DONE",
|
||||
"EQRES_H14EQ_FAIL",
|
||||
"EQRES_H14EQ_TIMEOUT",
|
||||
"EQRES_DONE",
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef __init_str_SYS_AEQ_TYPE
|
||||
static char *s__SYS_AEQ_TYPE[] = {
|
||||
"SysAEQ_OFF",
|
||||
"SysAEQ_RUN",
|
||||
"SysAEQ_DONE",
|
||||
};
|
||||
|
||||
#endif
|
||||
10
drivers/media/i2c/it66353/Kconfig
Normal file
10
drivers/media/i2c/it66353/Kconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config VIDEO_IT66353
|
||||
tristate "ITE IT66353 decoder"
|
||||
depends on I2C
|
||||
select HDMI
|
||||
help
|
||||
Support for the ITE IT66353 3 in 1 out HDMI switch.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called it66353.
|
||||
4
drivers/media/i2c/it66353/Makefile
Normal file
4
drivers/media/i2c/it66353/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ite-it66353-objs = it66353.o it66353_EQ.o it66353_opts.o
|
||||
obj-$(CONFIG_VIDEO_IT66353) += ite-it66353.o
|
||||
79
drivers/media/i2c/it66353/config.h
Normal file
79
drivers/media/i2c/it66353/config.h
Normal file
@@ -0,0 +1,79 @@
|
||||
// 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 _66353_CONFIG_H_
|
||||
#define _66353_CONFIG_H_
|
||||
|
||||
#ifndef _SHOW_PRAGMA_MSG
|
||||
#define message(ignore)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Switch register i2c address: 0x94(PCADR=0) or 0x96(PCADR=1)
|
||||
*/
|
||||
#define SWAddr 0xAC
|
||||
|
||||
/*
|
||||
* RX register i2c address ( programmable )
|
||||
*/
|
||||
#define RXAddr 0xB2
|
||||
|
||||
/*
|
||||
* CEC register i2c address ( programmable )
|
||||
*/
|
||||
#define CECAddr 0xC0
|
||||
|
||||
/*
|
||||
* EDID RAM i2c address ( programmable )
|
||||
*/
|
||||
#define RXEDIDAddr 0xa8
|
||||
|
||||
/*
|
||||
* Internal compile options:
|
||||
*/
|
||||
#define DEBUG_FSM_CHANGE 1
|
||||
#define USING_WDOG 0
|
||||
|
||||
/*
|
||||
* 66353 and 66354 don't need this:
|
||||
* set to 0
|
||||
*/
|
||||
#define CHECK_INT_BEFORE_TXOE 0
|
||||
|
||||
/*
|
||||
* EN_AUTO_RS: ( compile option )
|
||||
* 1: Enable Auto EQ code
|
||||
* 0: Disable Auto EQ code
|
||||
*/
|
||||
#define EN_H14_SKEW 0
|
||||
|
||||
/*
|
||||
* EN_AUTO_RS: ( compile option )
|
||||
* 1: Enable Auto EQ code
|
||||
* 0: Disable Auto EQ code
|
||||
*/
|
||||
#define EN_AUTO_RS 1
|
||||
|
||||
/*
|
||||
* EN_CEC:
|
||||
* 1: Enable CEC function
|
||||
* 0: Disable CEC function
|
||||
*/
|
||||
#define EN_CEC 0
|
||||
|
||||
/*
|
||||
* FIX_EDID_FOR_ATC_4BLOCK_CTS:
|
||||
* 1: For ATC 4 blocks EDID test
|
||||
*/
|
||||
#define FIX_EDID_FOR_ATC_4BLOCK_CTS 1
|
||||
|
||||
#endif // _66353_CONFIG_H_
|
||||
|
||||
41
drivers/media/i2c/it66353/debug.h
Normal file
41
drivers/media/i2c/it66353/debug.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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 _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "platform.h"
|
||||
|
||||
#define DBG_TXOE_1(x) { }
|
||||
#define DBG_TXOE_0(x) { }
|
||||
|
||||
#define DBG_CLKSTABLE_0(x) { }
|
||||
#define DBG_CLKSTABLE_1(x) { }
|
||||
|
||||
#define DBG_SYMLOCK_0(x) { }
|
||||
#define DBG_SYMLOCK_1(x) { }
|
||||
|
||||
enum {
|
||||
RX_SWITCH_PORT,
|
||||
RX_HPD_HIGH,
|
||||
RX_HPD_LOW,
|
||||
CLK_STABLE,
|
||||
CLK_UNSTABLE,
|
||||
AEQ_TOGGLE_HPD,
|
||||
TXOE0,
|
||||
TXOE1,
|
||||
};
|
||||
|
||||
#define DBG_TM(n) // { __debug_set_io(n); }
|
||||
int set_port(int portnum, int wrmask, int wrdata);
|
||||
void __debug_set_io(u8 n);
|
||||
#endif
|
||||
4535
drivers/media/i2c/it66353/it66353.c
Normal file
4535
drivers/media/i2c/it66353/it66353.c
Normal file
File diff suppressed because it is too large
Load Diff
83
drivers/media/i2c/it66353/it66353.h
Normal file
83
drivers/media/i2c/it66353/it66353.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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_H_
|
||||
#define _IT66353_H_
|
||||
|
||||
typedef struct {
|
||||
u8 EnRxDDCBypass;
|
||||
u8 EnableAutoEQ;
|
||||
} IT6635_DEVICE_OPTION;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ------------------------------
|
||||
// APIs:
|
||||
|
||||
char *it66353_get_lib_version(void);
|
||||
|
||||
void it66353_setup_edid_ram_phyaddr(u8 *edid, u8 block);
|
||||
void it66353_set_internal_EDID(u8 block, u8 *edid, u8 target_port);
|
||||
void it66353_get_internal_EDID(u8 block, u8 *edid, u8 target_port);
|
||||
void it66353_parse_edid_for_phyaddr(u8 *edid);
|
||||
bool it66353_read_one_block_edid(u8 block, u8 *edid_buffer);
|
||||
|
||||
#define SW_HPD_LOW 0
|
||||
#define SW_HPD_AUTO 1
|
||||
void it66353_force_rx_hpd(u8 hpd_state);
|
||||
|
||||
void it66353_set_option(IT6635_DEVICE_OPTION *Opts);
|
||||
void it66353_get_option(IT6635_DEVICE_OPTION *Opts);
|
||||
|
||||
u8 it66353_get_RS(void);
|
||||
void it66353_set_RS(u8 rs_idx0, u8 rs_idx1, u8 rs_idx2);
|
||||
void it66353_set_ch_RS(u8 ch, u8 rs_index);
|
||||
|
||||
void it66353_dump_register_all(void);
|
||||
void it66353_dump_opts(void);
|
||||
|
||||
u8 it66353_get_active_port(void);
|
||||
bool it66353_set_active_port(u8 port);
|
||||
|
||||
void it66353_change_default_RS(u8 port, u8 new_rs_idx0,
|
||||
u8 new_rs_idx1, u8 new_rs_idx2, u8 update_hw);
|
||||
|
||||
void it66353_set_rx_hpd(u8 hpd_value);
|
||||
void it66353_set_tx_5v(u8 output_value);
|
||||
bool it66353_toggle_hpd(u16 ms_duration);
|
||||
|
||||
bool it66353_auto_eq_adjust(void);
|
||||
|
||||
void it66353_dev_restart(void);
|
||||
void it66353_vars_init(void);
|
||||
void it66353_options_init(void);
|
||||
|
||||
/*
|
||||
* it6635 event handler:
|
||||
*/
|
||||
// static void it66353_dev_loop(void);
|
||||
|
||||
/*
|
||||
* platform dependent functions: (needs implementation)
|
||||
* u8 it66353_i2c_write(u8 addr, u8 offset, u8 length, u8 *buffer);
|
||||
* u8 it66353_i2c_read(u8 addr, u8 offset, u8 length, u8 *buffer);
|
||||
* static void it66353_i2c_read(u8 i2c_addr, u16 reg, u8 n, u8 *val);
|
||||
*/
|
||||
void delay1ms(u16 ms);
|
||||
__tick get_tick_count(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
935
drivers/media/i2c/it66353/it66353_EQ.c
Normal file
935
drivers/media/i2c/it66353/it66353_EQ.c
Normal file
@@ -0,0 +1,935 @@
|
||||
// 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
|
||||
*
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "platform.h"
|
||||
#include "debug.h"
|
||||
#include "it66353_drv.h"
|
||||
#include "it66353_EQ.h"
|
||||
#include "it66353.h"
|
||||
#include <linux/time.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
#define Channel_B 0
|
||||
#define Channel_G 1
|
||||
#define Channel_R 2
|
||||
|
||||
#define PR_ERR(...); {if (dbg_level >= 0) printk(__VA_ARGS__);}
|
||||
#define PR_INFO(...); {if (dbg_level >= 1) printk(__VA_ARGS__);}
|
||||
#define PR_INFO2(...); {if (dbg_level >= 2) printk(__VA_ARGS__);}
|
||||
#define PR_AEQ(...); {if (dbg_level >= 2) printk(__VA_ARGS__);}
|
||||
|
||||
const u8 it66353_rs_value[] = {0x7F, 0x7E, 0x3F, 0x3E, 0x1F, 0x1E, 0x0F,
|
||||
0x0E, 0x07, 0x06, 0x03, 0x02, 0x01, 0x00};
|
||||
static u8 rs_try_idx[] = {7, 6, 8, 5, 9, 4, 10, 3, 11, 2, 12, 1, 13, 0};
|
||||
static int dbg_level;
|
||||
#if 0
|
||||
static u8 _rx_is_h14_tmds_over_1G(void)
|
||||
{
|
||||
return it66353_get_port_info1(it66353_gdev.vars.Rx_active_port, PI_PLL_HS1G);
|
||||
}
|
||||
#endif
|
||||
|
||||
void it66353_rx_DFE_enable(u8 enable)
|
||||
{
|
||||
it66353_chgrxbank(3);
|
||||
if (enable)
|
||||
it66353_h2rxset(0x22, 0x40, 0x40); // Enable DFE
|
||||
else
|
||||
it66353_h2rxset(0x22, 0x40, 0x00); // Disable DFE
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
void it66353_rx_set_rs_3ch(u8 *rs_value)
|
||||
{
|
||||
u8 rs[3];
|
||||
|
||||
if (rs_value) {
|
||||
rs[0] = rs_value[0] | 0x80;
|
||||
rs[1] = rs_value[1] | 0x80;
|
||||
rs[2] = rs_value[2] | 0x80;
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxbwr(0x27, 3, rs);
|
||||
rs[0] = 0xCC;
|
||||
rs[1] = 0xCC;
|
||||
rs[2] = 0xCC;
|
||||
it66353_h2rxbrd(0x27, 3, rs);
|
||||
it66353_chgrxbank(0);
|
||||
// it66353_h2rxwr(0x0f, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
void it66353_rx_set_rs(u8 ch, u8 rs_value)
|
||||
{
|
||||
rs_value |= 0x80;
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxwr(0x27 + ch, rs_value);
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static u8 _rx_get_rs(u8 ch)
|
||||
{
|
||||
u8 rs_value;
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
rs_value = it66353_h2rxrd(0x27+ch);
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
return rs_value;
|
||||
}
|
||||
#endif
|
||||
|
||||
void it66353_rx_clear_ced_err(void)
|
||||
{
|
||||
// read CED Error from SAREQ CEDError Counter
|
||||
it66353_h2rxset(0x3B, 0x08, 0x08);
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxset(0x55, 0x80, 0x00);
|
||||
it66353_h2rxwr(0xe9, 0x80);
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
static void _rx_ced_err_recheck(void)
|
||||
{
|
||||
u8 i;
|
||||
u8 tmp;
|
||||
|
||||
it66353_h2rxwr(0xB9, 0xFF);
|
||||
it66353_h2rxwr(0xBE, 0xFF);
|
||||
msleep(10);
|
||||
|
||||
for (i = 0 ; i < 3 ; i++) {
|
||||
if ((it66353_gdev.vars.RxCEDErrValid&(1 << i)) &&
|
||||
(it66353_gdev.vars.RxCEDErr[i] > 0x100)) {
|
||||
if ((it66353_h2rxrd(0x19)&0x80)) {
|
||||
tmp = it66353_h2rxrd(0xB9);
|
||||
if (0 == (tmp & (0x03<<i)))
|
||||
it66353_gdev.vars.RxCEDErr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void it66353_rx_update_ced_err_from_hw(void)
|
||||
{
|
||||
u8 symlock;
|
||||
|
||||
if (it66353_rx_is_clock_stable()) {
|
||||
symlock = it66353_h2rxrd(0x14);
|
||||
|
||||
if (0 == (symlock & 0x38)) {
|
||||
it66353_gdev.vars.RxCEDErrValid = 0;
|
||||
} else {
|
||||
// read CED Error from SAREQ CEDError Counter
|
||||
it66353_h2rxset(0x3B, 0x08, 0x08);
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxset(0x55, 0x80, 0x00);
|
||||
|
||||
if (symlock & 0x08) {
|
||||
it66353_h2rxwr(0xe9, 0x00);
|
||||
it66353_gdev.vars.RxCEDErr[0] = it66353_h2rxrd(0xEB);
|
||||
// ced valid
|
||||
if (it66353_gdev.vars.RxCEDErr[0] & 0x80) {
|
||||
it66353_gdev.vars.RxCEDErr[0] = it66353_gdev.vars.RxCEDErr[0] & 0x7F;
|
||||
it66353_gdev.vars.RxCEDErr[0] = (it66353_gdev.vars.RxCEDErr[0] << 8) +
|
||||
it66353_h2rxrd(0xEA);
|
||||
it66353_gdev.vars.RxCEDErrValid = 1;
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid = 0;
|
||||
}
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid = 0;
|
||||
}
|
||||
|
||||
if (symlock & 0x10) {
|
||||
it66353_h2rxwr(0xe9, 0x20);
|
||||
it66353_gdev.vars.RxCEDErr[1] = it66353_h2rxrd(0xEB);
|
||||
|
||||
if (it66353_gdev.vars.RxCEDErr[1] & 0x80) {
|
||||
it66353_gdev.vars.RxCEDErr[1] = it66353_gdev.vars.RxCEDErr[1] & 0x7F;
|
||||
it66353_gdev.vars.RxCEDErr[1] = (it66353_gdev.vars.RxCEDErr[1]<<8) +
|
||||
it66353_h2rxrd(0xEA);
|
||||
it66353_gdev.vars.RxCEDErrValid |= 0x02;
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid &= ~0x02;
|
||||
}
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid &= ~0x02;
|
||||
}
|
||||
|
||||
if (symlock & 0x20) {
|
||||
it66353_h2rxwr(0xe9, 0x40);
|
||||
it66353_gdev.vars.RxCEDErr[2] = it66353_h2rxrd(0xEB);
|
||||
|
||||
if (it66353_gdev.vars.RxCEDErr[2] & 0x80) {
|
||||
it66353_gdev.vars.RxCEDErr[2] = it66353_gdev.vars.RxCEDErr[2] & 0x7F;
|
||||
it66353_gdev.vars.RxCEDErr[2] = (it66353_gdev.vars.RxCEDErr[2]<<8) +
|
||||
it66353_h2rxrd(0xEA);
|
||||
it66353_gdev.vars.RxCEDErrValid |= 0x04;
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid &= ~0x04;
|
||||
}
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid &= ~0x04;
|
||||
}
|
||||
|
||||
it66353_h2rxwr(0xe9, 0x80);
|
||||
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
_rx_ced_err_recheck();
|
||||
|
||||
}
|
||||
} else {
|
||||
it66353_gdev.vars.RxCEDErrValid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void _rx_record_ced_err(void)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (it66353_gdev.EQ.ced_acc_count == 0) {
|
||||
for (i = 0 ; i < 3 ; i++) {
|
||||
it66353_gdev.EQ.ced_err_avg[i] = it66353_gdev.vars.RxCEDErr[i];
|
||||
// it66353_gdev.EQ.ced_err_avg_prev[i] = 0x8888;
|
||||
}
|
||||
} else {
|
||||
for (i = 0 ; i < 3 ; i++) {
|
||||
it66353_gdev.EQ.ced_err_avg[i] = it66353_gdev.EQ.ced_err_avg[i] +
|
||||
it66353_gdev.vars.RxCEDErr[i];
|
||||
it66353_gdev.EQ.ced_err_avg[i] >>= 1;
|
||||
}
|
||||
}
|
||||
it66353_gdev.EQ.ced_acc_count++;
|
||||
}
|
||||
|
||||
u8 it66353_rx_monitor_ced_err(void)
|
||||
{
|
||||
static u8 err_acc;
|
||||
|
||||
if (0 == it66353_rx_is_all_ch_symlock()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_rx_record_ced_err();
|
||||
|
||||
|
||||
if (it66353_gdev.vars.RxCEDErrValid) {
|
||||
if ((it66353_gdev.vars.RxCEDErr[0] || it66353_gdev.vars.RxCEDErr[1] ||
|
||||
it66353_gdev.vars.RxCEDErr[2])) {
|
||||
err_acc++;
|
||||
|
||||
if (err_acc > 10) {
|
||||
err_acc = 0;
|
||||
if ((it66353_gdev.vars.RxCEDErr[0] > 0x08 ||
|
||||
it66353_gdev.vars.RxCEDErr[1] > 0x08 ||
|
||||
it66353_gdev.vars.RxCEDErr[2] > 0x08)) {
|
||||
// return 1, means too much CED
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err_acc = 0;
|
||||
}
|
||||
} else {
|
||||
// no ced error value for reference
|
||||
// do nothing about CED error
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 it66353_rx_is_hdmi20(void)
|
||||
{
|
||||
#if 1
|
||||
return it66353_gdev.vars.clock_ratio;
|
||||
#else
|
||||
if (it66353_h2swrd(0x61 + it66353_gdev.vars.Rx_active_port * 3) & 0x40) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if EN_H14_SKEW
|
||||
void it66353_rx_skew_adj(u8 ch)
|
||||
{
|
||||
static u8 idx[3] = {0};
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxset(0x2D, 0x1 << ch, 0x01 << ch);
|
||||
switch (idx[ch]) {
|
||||
case 0:
|
||||
it66353_h2rxset(0x2C, 0x3 << ch, 0x02 << ch);
|
||||
idx[ch] = 1;
|
||||
break;
|
||||
case 1:
|
||||
it66353_h2rxset(0x2C, 0x3 << ch, 0x03 << ch);
|
||||
idx[ch] = 2;
|
||||
break;
|
||||
case 2:
|
||||
it66353_h2rxset(0x2C, 0x3 << ch, 0x00 << ch);
|
||||
idx[ch] = 0;
|
||||
break;
|
||||
default:
|
||||
idx[ch] = 0;
|
||||
break;
|
||||
}
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void it66353_eq_save_h20(void)
|
||||
{
|
||||
it66353_chgrxbank(3);
|
||||
it66353_gdev.EQ.stored_RS_20[0] = it66353_h2rxrd(0x27);
|
||||
it66353_gdev.EQ.stored_RS_20[1] = it66353_h2rxrd(0x28);
|
||||
it66353_gdev.EQ.stored_RS_20[2] = it66353_h2rxrd(0x29);
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
void it66353_eq_load_h20(void)
|
||||
{
|
||||
PR_INFO("enter it66353_eq_load_h20\r\n");
|
||||
it66353_rx_set_rs_3ch(it66353_gdev.EQ.stored_RS_20);
|
||||
it66353_aeq_set_DFE2(it66353_gdev.EQ.stored_RS_20[0], it66353_gdev.EQ.stored_RS_20[1],
|
||||
it66353_gdev.EQ.stored_RS_20[2]);
|
||||
it66353_rx_DFE_enable(1);
|
||||
}
|
||||
|
||||
void it66353_eq_save_h14(void)
|
||||
{
|
||||
it66353_chgrxbank(3);
|
||||
it66353_gdev.EQ.stored_RS_14[0] = it66353_h2rxrd(0x27);
|
||||
it66353_gdev.EQ.stored_RS_14[1] = it66353_h2rxrd(0x28);
|
||||
it66353_gdev.EQ.stored_RS_14[2] = it66353_h2rxrd(0x29);
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
void it66353_eq_load_h14(void)
|
||||
{
|
||||
PR_INFO("enter it66353_eq_load_h14\r\n");
|
||||
it66353_rx_set_rs_3ch(it66353_gdev.EQ.stored_RS_14);
|
||||
}
|
||||
|
||||
void it66353_eq_load_previous(void)
|
||||
{
|
||||
if (it66353_rx_is_hdmi20()) {
|
||||
if (it66353_gdev.EQ.current_eq_mode == 0) {
|
||||
it66353_gdev.EQ.current_eq_mode = 1;
|
||||
it66353_eq_load_h20();
|
||||
}
|
||||
} else {
|
||||
if (it66353_gdev.EQ.current_eq_mode == 1) {
|
||||
it66353_gdev.EQ.current_eq_mode = 0;
|
||||
it66353_eq_load_h14();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void it66353_eq_load_default(void)
|
||||
{
|
||||
it66353_rx_set_rs_3ch(it66353_gdev.opts.active_rx_opt->DefaultEQ);
|
||||
|
||||
if (it66353_rx_is_hdmi20()) {
|
||||
it66353_rx_DFE_enable(0);
|
||||
// PR_INFO(("_eq_load_def_20\r\n"));
|
||||
} else {
|
||||
// PR_INFO(("_eq_load_def_14\r\n"));
|
||||
}
|
||||
}
|
||||
|
||||
static u8 _eq_find_rs_index(u8 EQ_Value)
|
||||
{
|
||||
u8 i = 0;
|
||||
EQ_Value &= ~0x80;
|
||||
for (i = 0; i < sizeof(it66353_rs_value); i++) {
|
||||
if (it66353_rs_value[i] == EQ_Value)
|
||||
return i;
|
||||
}
|
||||
|
||||
PR_ERR("EQ %02X not found !!\r\n", EQ_Value);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void it66353_eq_reset_txoe_ready(void)
|
||||
{
|
||||
it66353_gdev.EQ.txoe_ready20 = 0;
|
||||
it66353_gdev.EQ.txoe_ready14 = 0;
|
||||
}
|
||||
|
||||
void it66353_eq_set_txoe_ready(u8 ready)
|
||||
{
|
||||
if (it66353_rx_is_hdmi20())
|
||||
it66353_gdev.EQ.txoe_ready20 = ready;
|
||||
else
|
||||
it66353_gdev.EQ.txoe_ready14 = ready;
|
||||
|
||||
PR_INFO("set ready 14=%d 20=%d\r\n", it66353_gdev.EQ.txoe_ready14,
|
||||
it66353_gdev.EQ.txoe_ready20);
|
||||
}
|
||||
|
||||
u8 it66353_eq_get_txoe_ready(void)
|
||||
{
|
||||
PR_INFO("get ready 14=%d 20=%d\r\n", it66353_gdev.EQ.txoe_ready14,
|
||||
it66353_gdev.EQ.txoe_ready20);
|
||||
if (it66353_rx_is_hdmi20()) {
|
||||
return it66353_gdev.EQ.txoe_ready20;
|
||||
} else {
|
||||
return it66353_gdev.EQ.txoe_ready14;
|
||||
}
|
||||
}
|
||||
|
||||
void it66353_eq_reset_state(void)
|
||||
{
|
||||
it66353_gdev.EQ.EQ_flag_20 = SysAEQ_RUN;
|
||||
it66353_gdev.EQ.EQ_flag_14 = SysAEQ_RUN;
|
||||
}
|
||||
|
||||
void it66353_eq_set_state(u8 state)
|
||||
{
|
||||
if (it66353_rx_is_hdmi20()) {
|
||||
it66353_gdev.EQ.EQ_flag_20 = state;
|
||||
} else {
|
||||
it66353_gdev.EQ.EQ_flag_14 = state;
|
||||
}
|
||||
|
||||
PR_INFO("set eq flag 14=%d 20=%d\r\n", it66353_gdev.EQ.EQ_flag_14,
|
||||
it66353_gdev.EQ.EQ_flag_20);
|
||||
}
|
||||
|
||||
u8 it66353_eq_get_state(void)
|
||||
{
|
||||
PR_INFO("get eq flag 14=%d 20=%d\r\n", it66353_gdev.EQ.EQ_flag_14,
|
||||
it66353_gdev.EQ.EQ_flag_20);
|
||||
|
||||
if (it66353_rx_is_hdmi20()) {
|
||||
return it66353_gdev.EQ.EQ_flag_20;
|
||||
} else {
|
||||
return it66353_gdev.EQ.EQ_flag_14;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 _aeq_ready_to_start(void)
|
||||
{
|
||||
return it66353_rx_is_clock_stable();
|
||||
}
|
||||
|
||||
void it66353_aeq_diable_eq_trigger(void)
|
||||
{
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxset(0x22, 0x04, 0x00);
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
static void _aeq_reset(void)
|
||||
{
|
||||
it66353_aeq_diable_eq_trigger();
|
||||
|
||||
it66353_h2rxwr(0x07, 0xff);
|
||||
it66353_h2rxwr(0x23, 0xB0);
|
||||
msleep(10);
|
||||
it66353_h2rxwr(0x23, 0xA0);
|
||||
}
|
||||
|
||||
static void _aeq_get_DFE2(u8 ch, u8 rs_idx)
|
||||
{
|
||||
u8 i;
|
||||
u8 amp_a, amp_b, amp_c, amp_d;
|
||||
u8 tap1_sign, tap1_value;
|
||||
u8 tap2_sign, tap2_value;
|
||||
u8 tap3_sign, tap3_value;
|
||||
u8 dfe_a, dfe_b, dfe_c;
|
||||
u8 reg37o, reg37;
|
||||
u8 rec[4];
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
|
||||
i = rs_idx;
|
||||
|
||||
it66353_h2rxset(0x36, 0x0F, i);
|
||||
reg37o = it66353_h2rxrd(0x37) & (~0xC0);
|
||||
PR_AEQ("RS=%02x DEF:\r\n", 0x80|it66353_rs_value[i]);
|
||||
|
||||
for (ch = 0 ; ch < 3 ; ch++) {
|
||||
// hdmirxset(0x37 ,0xC0 ,ch<<6);
|
||||
reg37 = reg37o | (ch << 6);
|
||||
it66353_h2rxwr(0x37, reg37);
|
||||
|
||||
#if 0
|
||||
amp_a = hdmirxrd(0x5d);
|
||||
amp_b = hdmirxrd(0x5e);
|
||||
amp_c = hdmirxrd(0x5f);
|
||||
amp_d = hdmirxrd(0x60);
|
||||
#else
|
||||
it66353_h2rxbrd(0x5d, 4, rec);
|
||||
amp_a = rec[0];
|
||||
amp_b = rec[1];
|
||||
amp_c = rec[2];
|
||||
amp_d = rec[3];
|
||||
#endif
|
||||
|
||||
if (amp_a > amp_b) {
|
||||
tap1_sign = 1;
|
||||
tap1_value = (amp_a - amp_b) >> 1;
|
||||
} else {
|
||||
tap1_sign = 0;
|
||||
tap1_value = (amp_b - amp_a) >> 1;
|
||||
}
|
||||
|
||||
if (amp_a > amp_c) {
|
||||
tap2_sign = 1;
|
||||
tap2_value = (amp_a - amp_c) >> 1;
|
||||
} else {
|
||||
tap2_sign = 0;
|
||||
tap2_value = (amp_c - amp_a) >> 1;
|
||||
}
|
||||
|
||||
if (amp_a > amp_d) {
|
||||
tap3_sign = 1;
|
||||
tap3_value = (amp_a - amp_d) >> 1;
|
||||
} else {
|
||||
tap3_sign = 0;
|
||||
tap3_value = (amp_d - amp_a) >> 1;
|
||||
}
|
||||
|
||||
if (tap1_value > 0x1F)
|
||||
tap1_value = 0x1F;
|
||||
if (tap2_value > 0x0F)
|
||||
tap2_value = 0x0F;
|
||||
if (tap3_value > 0x07)
|
||||
tap3_value = 0x07;
|
||||
|
||||
dfe_a = (0x40) + (tap1_sign << 5) + tap1_value;
|
||||
dfe_b = (0x20) + (tap2_sign << 4) + tap2_value;
|
||||
dfe_c = (0x10) + (tap3_sign << 3) + tap3_value;
|
||||
|
||||
it66353_gdev.EQ.DFE[i][ch][0] = dfe_a;
|
||||
it66353_gdev.EQ.DFE[i][ch][1] = dfe_b;
|
||||
it66353_gdev.EQ.DFE[i][ch][2] = dfe_c;
|
||||
|
||||
PR_AEQ(" ch%d=%02X %02X %02X |", ch, dfe_a, dfe_b, dfe_c);
|
||||
}
|
||||
PR_AEQ("\r\n");
|
||||
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
}
|
||||
|
||||
void it66353_aeq_set_DFE2(u8 EQ0, u8 EQ1, u8 EQ2)
|
||||
{
|
||||
u8 dfe[9];
|
||||
u8 i;
|
||||
|
||||
i = _eq_find_rs_index(EQ0);
|
||||
_aeq_get_DFE2(0, i);
|
||||
dfe[0] = it66353_gdev.EQ.DFE[i][Channel_B][0];
|
||||
dfe[1] = it66353_gdev.EQ.DFE[i][Channel_B][1];
|
||||
dfe[2] = it66353_gdev.EQ.DFE[i][Channel_B][2];
|
||||
|
||||
i = _eq_find_rs_index(EQ1);
|
||||
_aeq_get_DFE2(1, i);
|
||||
dfe[3] = it66353_gdev.EQ.DFE[i][Channel_G][0];
|
||||
dfe[4] = it66353_gdev.EQ.DFE[i][Channel_G][1];
|
||||
dfe[5] = it66353_gdev.EQ.DFE[i][Channel_G][2];
|
||||
|
||||
i = _eq_find_rs_index(EQ2);
|
||||
_aeq_get_DFE2(2, i);
|
||||
dfe[6] = it66353_gdev.EQ.DFE[i][Channel_R][0];
|
||||
dfe[7] = it66353_gdev.EQ.DFE[i][Channel_R][1];
|
||||
dfe[8] = it66353_gdev.EQ.DFE[i][Channel_R][2];
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxbwr(0x4B, 9, dfe);
|
||||
// it66353_h2rxbrd(0x4B, 9, dfe); // for recheck only
|
||||
for (i = 0; i < 3; i++) {
|
||||
PR_AEQ("DFE:CH%d=%02X %02X %02X\r\n",
|
||||
i, dfe[0+i*3], dfe[1+i*3], dfe[2+i*3]);
|
||||
}
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
static void _aeq_get_calc_rs(void)
|
||||
{
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxbrd(0xD5, 3, it66353_gdev.EQ.CalcRS);
|
||||
it66353_chgrxbank(0);
|
||||
PR_AEQ("AEQ RS=%02X %02X %02X\r\n",
|
||||
it66353_gdev.EQ.CalcRS[0], it66353_gdev.EQ.CalcRS[1], it66353_gdev.EQ.CalcRS[2]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void _aeq_trigger_EQ(void)
|
||||
{
|
||||
_aeq_reset();
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
|
||||
// if 1G~3G, need to force set CSEL to 110
|
||||
if (_rx_is_h14_tmds_over_1G()) {
|
||||
PR_AEQ("over 1G\r\n");
|
||||
it66353_h2rxwr(0x20, 0x36);
|
||||
it66353_h2rxwr(0x21, 0x0E);
|
||||
} else {
|
||||
PR_AEQ("under 1G\r\n");
|
||||
it66353_h2rxwr(0x20, 0x1B);
|
||||
it66353_h2rxwr(0x21, 0x03);
|
||||
}
|
||||
|
||||
it66353_h2rxwr(0x26, 0x00);
|
||||
it66353_h2rxwr(0x22, 0x38); // [5:3] AUTOAMP , AUTOEQ , EQPWDB
|
||||
it66353_h2rxset(0x22, 0x04, 0x04); // Trigger EQ
|
||||
msleep(1);
|
||||
it66353_h2rxset(0x22, 0x04, 0x00); // Trigger EQ
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
it66353_gdev.EQ.AutoEQ_WaitTime = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _aeq_trigger_SAREQ(void)
|
||||
{
|
||||
// MUST disable EQTrg before EQRst
|
||||
u8 def_opt = 1;
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
// init CSC value
|
||||
it66353_h2rxwr(0x20, 0x1B);
|
||||
it66353_h2rxwr(0x21, 0x03);
|
||||
it66353_h2rxset(0x20, 0x80, 0x00); // disable CLKStb AutoEQTrg
|
||||
it66353_h2rxwr(0x22, 0x00); // disable [4] ENDFE, set [2] EQTrg low
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
_aeq_reset();
|
||||
|
||||
it66353_h2rxwr(0x3B, 0x03); // Reg_CEDOPT[5:0]
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
|
||||
it66353_h2rxwr(0x26, 0x00);
|
||||
// it66353_h2rxwr(0x27, 0x1F);
|
||||
// it66353_h2rxwr(0x28, 0x1F);
|
||||
// it66353_h2rxwr(0x29, 0x1F);
|
||||
it66353_h2rxset(0x27, 0x80, 0x00);
|
||||
it66353_h2rxset(0x28, 0x80, 0x00);
|
||||
it66353_h2rxset(0x29, 0x80, 0x00);
|
||||
|
||||
it66353_h2rxset(0x2C, 0xC0, 0xC0);
|
||||
// it66353_h2rxset(0x2D, 0xF0, 0x20);
|
||||
it66353_h2rxset(0x2D, 0xF0, 0x20+(def_opt<<4)); // rsdfeopt=1
|
||||
it66353_h2rxset(0x2D, 0x07, 0x00);
|
||||
it66353_h2rxwr(0x30, 0x8C);
|
||||
|
||||
it66353_h2rxwr(0x31, 0xB0); // AMPTime[7:0]
|
||||
|
||||
it66353_h2rxwr(0x32, 0x43);
|
||||
it66353_h2rxwr(0x33, 0x47);
|
||||
it66353_h2rxwr(0x34, 0x4B);
|
||||
it66353_h2rxwr(0x35, 0x53);
|
||||
|
||||
it66353_h2rxset(0x36, 0xc0, 0x00); // [7:6] AMPTime[9:8]
|
||||
|
||||
it66353_h2rxwr(0x37, 0x0B); // [7:6] RecChannel, [4]: RSOnestage,
|
||||
// [3] IgnoreOPT, [1:0] MacthNoSel
|
||||
|
||||
it66353_h2rxwr(0x38, 0xF2); // [7:4] MonTime
|
||||
/* [5] POLBOPT, [4] ADDPClrOPT, [3:0] CED Valid Threshold 0x0D */
|
||||
it66353_h2rxwr(0x39, 0x04);
|
||||
it66353_h2rxset(0x4A, 0x80, 0x00);
|
||||
it66353_h2rxset(0x4B, 0x80, 0x00);
|
||||
it66353_h2rxset(0x54, 0x80, 0x80); // Reg_EN_PREEQ
|
||||
it66353_h2rxset(0x54, 0x38, 0x38);
|
||||
|
||||
it66353_h2rxwr(0x55, 0x40); // RSM Threshold
|
||||
|
||||
// it66353_h2rxset(0x22, 0x04, 0x04); // Trigger EQ
|
||||
it66353_h2rxset(0x22, 0x44, 0x04+(def_opt<<6)); // Trigger EQ
|
||||
it66353_chgrxbank(0);
|
||||
|
||||
it66353_gdev.EQ.AutoEQ_WaitTime = 0;
|
||||
}
|
||||
|
||||
static void _aeq_check_amp_and_rs_status(void)
|
||||
{
|
||||
u8 i;
|
||||
u8 reg63, reg6D;
|
||||
u16 reg64, reg6E;
|
||||
u16 amp_timeout;
|
||||
|
||||
it66353_gdev.EQ.DFE_Valid = 1;
|
||||
it66353_gdev.EQ.RS_Valid = 1;
|
||||
|
||||
it66353_chgrxbank(3);
|
||||
for (i = 0; i < 3; i++) {
|
||||
it66353_h2rxset(0x37, 0xC0, i<<6);
|
||||
reg63 = it66353_h2rxrd(0x63);
|
||||
reg64 = it66353_h2rxrd(0x64)&0x3F;
|
||||
reg6D = it66353_h2rxrd(0x6D);
|
||||
reg6E = it66353_h2rxrd(0x6E);
|
||||
|
||||
it66353_gdev.EQ.RS_ValidMap[i] = (reg6E<<8) + reg6D;
|
||||
amp_timeout = (reg64<<8) + reg63;
|
||||
|
||||
PR_AEQ("CH %d, AMP_TimeOut = 0x%04X \r\n", i, amp_timeout);
|
||||
PR_AEQ("CH %d, RS_ValidMap = 0x%04X \r\n", i,
|
||||
it66353_gdev.EQ.RS_ValidMap[i]);
|
||||
|
||||
if (amp_timeout == 0x3FFF) {
|
||||
it66353_gdev.EQ.DFE_Valid = 0;
|
||||
}
|
||||
|
||||
reg63 = it66353_h2rxrd(0x61);
|
||||
reg64 = it66353_h2rxrd(0x62) & 0x3F;
|
||||
amp_timeout = (reg64 << 8) + reg63;
|
||||
|
||||
PR_AEQ("CH %d, AMP_Done = 0x%04X \r\n", i, amp_timeout);
|
||||
|
||||
if (it66353_gdev.EQ.RS_ValidMap[i] == 0x0000) {
|
||||
it66353_gdev.EQ.RS_Valid = 0;
|
||||
}
|
||||
}
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
|
||||
u8 it66353_aeq_check_sareq_result(void)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
tmp = it66353_h2rxrd(0x07);
|
||||
if (tmp & (0x20 | 0x10)) { // EQ fail | EQ Done
|
||||
it66353_aeq_diable_eq_trigger();
|
||||
_aeq_check_amp_and_rs_status();
|
||||
if (tmp & 0x10) {
|
||||
it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_DONE;
|
||||
} else {
|
||||
it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_FAIL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* else if (tmp & BIT5) { // EQ fail
|
||||
* it66353_aeq_diable_eq_trigger();
|
||||
* _aeq_check_amp_and_rs_status();
|
||||
* it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_FAIL;
|
||||
* }
|
||||
*/
|
||||
else {
|
||||
it66353_gdev.EQ.AutoEQ_WaitTime++;
|
||||
msleep(20);
|
||||
if (it66353_gdev.EQ.AutoEQ_WaitTime > 30) {
|
||||
it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_TIMEOUT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static u8 _aeq_check_h14eq_result(void)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
tmp = it66353_h2rxrd(0x07);
|
||||
if (tmp & 0x40) { // EQ Done
|
||||
it66353_aeq_diable_eq_trigger();
|
||||
PR_AEQ("AEQ 14, DONE\r\n");
|
||||
return EQRES_H14EQ_DONE;
|
||||
} else if (tmp & 0x80) { // EQ fail
|
||||
it66353_aeq_diable_eq_trigger();
|
||||
PR_ERR("AEQ 14, FAIL\r\n");
|
||||
return EQRES_H14EQ_FAIL;
|
||||
} else {
|
||||
msleep(25);
|
||||
it66353_gdev.EQ.AutoEQ_WaitTime++;
|
||||
if (it66353_gdev.EQ.AutoEQ_WaitTime > 100) {
|
||||
it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_TIMEOUT;
|
||||
PR_ERR("AEQ 14, TIMEOUT\r\n");
|
||||
return EQRES_H14EQ_TIMEOUT;
|
||||
} else {
|
||||
// return EQRES_BUSY;
|
||||
}
|
||||
|
||||
}
|
||||
return EQRES_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
static u8 _meq_14(void)
|
||||
{
|
||||
u8 rs_idx;
|
||||
static u8 ch_rs_idx[3];
|
||||
u8 ch;
|
||||
u8 ch_all_done;
|
||||
u8 ch_done[3];
|
||||
u8 res = EQRES_H14EQ_FAIL;
|
||||
|
||||
ch_done[0] = 0;
|
||||
ch_done[1] = 0;
|
||||
ch_done[2] = 0;
|
||||
ch_all_done = 0;
|
||||
ch_rs_idx[0] = 0;
|
||||
ch_rs_idx[1] = 0;
|
||||
ch_rs_idx[2] = 0;
|
||||
|
||||
it66353_rx_clear_ced_err();
|
||||
msleep(50);
|
||||
|
||||
|
||||
for (rs_idx = 0; rs_idx < 14; rs_idx++) {
|
||||
if (0 == _aeq_ready_to_start()) {
|
||||
PR_ERR("Cannot perform EQ adjust\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
it66353_rx_update_ced_err_from_hw();
|
||||
|
||||
for (ch = 0; ch < 3; ch++) {
|
||||
if (ch_done[ch]) {
|
||||
// break;
|
||||
}
|
||||
|
||||
if (it66353_gdev.vars.RxCEDErrValid & (1 << ch)) {
|
||||
if (it66353_gdev.vars.RxCEDErr[ch] < 0x01) {
|
||||
ch_done[ch] = 1;
|
||||
ch_all_done++;
|
||||
PR_AEQ("RS good ch%d = %02X\r\n",
|
||||
ch, it66353_rs_value[ch_rs_idx[ch]]);
|
||||
} else {
|
||||
ch_done[ch] = 0;
|
||||
PR_AEQ("RS NG ch%d = %02X, err=%04X\r\n",
|
||||
ch, it66353_rs_value[ch_rs_idx[ch]],
|
||||
it66353_gdev.vars.RxCEDErr[ch]);
|
||||
}
|
||||
} else {
|
||||
ch_done[ch] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch_done[0] && ch_done[1] && ch_done[2]) {
|
||||
PR_AEQ("ch_all_done\r\n");
|
||||
res = EQRES_H14EQ_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
it66353_rx_clear_ced_err();
|
||||
for (ch = 0; ch < 3; ch++) {
|
||||
if (0 == ch_done[ch]) {
|
||||
it66353_rx_set_rs(ch, it66353_rs_value[rs_try_idx[ch_rs_idx[ch]]]);
|
||||
ch_rs_idx[ch]++;
|
||||
if (ch_rs_idx[ch] >= 14) {
|
||||
ch_rs_idx[ch] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool it66353_auto_eq_adjust(void)
|
||||
{
|
||||
u8 result;
|
||||
u8 ret = false;
|
||||
|
||||
if (_aeq_ready_to_start()) {
|
||||
it66353_h2swset(0xD4, 0x03, 0x01); // Set TXOE off
|
||||
|
||||
if (it66353_gdev.vars.count_auto_eq_fail > 13) {
|
||||
it66353_gdev.vars.count_auto_eq_fail = 0;
|
||||
it66353_rx_caof_init(it66353_gdev.vars.Rx_active_port);
|
||||
}
|
||||
|
||||
if (it66353_rx_is_hdmi20()) {
|
||||
it66353_gdev.EQ.current_eq_mode = EQ_MODE_H20;
|
||||
it66353_gdev.EQ.RS_Valid = 0;
|
||||
it66353_gdev.EQ.DFE_Valid = 0;
|
||||
_aeq_trigger_SAREQ();
|
||||
|
||||
while (it66353_aeq_check_sareq_result() == 0) {
|
||||
// auto EQ will wait about 400ms here
|
||||
}
|
||||
|
||||
if (it66353_gdev.EQ.DFE_Valid && it66353_gdev.EQ.RS_Valid) {
|
||||
_aeq_get_calc_rs();
|
||||
it66353_rx_set_rs_3ch(it66353_gdev.EQ.CalcRS);
|
||||
it66353_aeq_set_DFE2(it66353_gdev.EQ.CalcRS[0],
|
||||
it66353_gdev.EQ.CalcRS[1],
|
||||
it66353_gdev.EQ.CalcRS[2]);
|
||||
it66353_rx_DFE_enable(1);
|
||||
|
||||
it66353_eq_save_h20();
|
||||
|
||||
ret = true;
|
||||
} else {
|
||||
it66353_chgrxbank(3);
|
||||
it66353_h2rxset(0x27, 0x80, 0x80);
|
||||
it66353_h2rxset(0x28, 0x80, 0x80);
|
||||
it66353_h2rxset(0x29, 0x80, 0x80);
|
||||
it66353_chgrxbank(0);
|
||||
}
|
||||
} else {
|
||||
it66353_gdev.EQ.current_eq_mode = EQ_MODE_H14;
|
||||
|
||||
#if 0
|
||||
_aeq_trigger_EQ();
|
||||
|
||||
result = _aeq_check_h14eq_result();
|
||||
while (EQRES_BUSY == result) {
|
||||
result = _aeq_check_h14eq_result();
|
||||
}
|
||||
|
||||
if (result == EQRES_H14EQ_DONE) {
|
||||
_aeq_get_calc_rs();
|
||||
it66353_rx_set_rs_3ch(it66353_gdev.EQ.CalcRS);
|
||||
} else {
|
||||
result = _meq_14();
|
||||
}
|
||||
#else
|
||||
result = _meq_14();
|
||||
#endif
|
||||
|
||||
if (result == EQRES_H14EQ_DONE) {
|
||||
it66353_eq_save_h14();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
it66353_h2swset(0xD4, 0x03, 0x00); // Set DRV_RST='1'
|
||||
|
||||
if (ret) {
|
||||
it66353_gdev.vars.count_auto_eq_fail = 0;
|
||||
} else {
|
||||
it66353_gdev.vars.count_auto_eq_fail++;
|
||||
PR_ERR("EQ result NG %d\r\n", it66353_gdev.vars.count_auto_eq_fail);
|
||||
}
|
||||
} else {
|
||||
PR_ERR("EQ adjust not available\r\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
20
drivers/media/i2c/it66353/it66353_EQ.h
Normal file
20
drivers/media/i2c/it66353/it66353_EQ.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// 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_EQH
|
||||
#define it66353_EQH
|
||||
|
||||
// #define it66353_eq_reset_state(x)\
|
||||
// { it66353_gdev.EQ.EQ_flag_20 = SysAEQ_RUN; it66353_gdev.EQ.EQ_flag_14 = SysAEQ_RUN; }
|
||||
// #define _eq_reset_txoe(x)\
|
||||
// { it66353_gdev.EQ.txoe_ready20 = 0; it66353_gdev.EQ.txoe_ready14 = 0; }
|
||||
|
||||
#endif
|
||||
458
drivers/media/i2c/it66353/it66353_drv.h
Normal file
458
drivers/media/i2c/it66353/it66353_drv.h
Normal file
@@ -0,0 +1,458 @@
|
||||
// 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
|
||||
160
drivers/media/i2c/it66353/it66353_opts.c
Normal file
160
drivers/media/i2c/it66353/it66353_opts.c
Normal file
@@ -0,0 +1,160 @@
|
||||
// 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
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include "config.h"
|
||||
#include "platform.h"
|
||||
#include "debug.h"
|
||||
#include "it66353_drv.h"
|
||||
#include "it66353_EQ.h"
|
||||
#include "it66353.h"
|
||||
|
||||
/*
|
||||
* TX_PN_SWAP
|
||||
* 1: Enable TX side TMDS P/N swap
|
||||
* 0: Disable TX side TMDS P/N swap
|
||||
*/
|
||||
#define TX_PN_SWAP 0
|
||||
#ifndef TX_PN_SWAP
|
||||
|
||||
#pragma message("TX_PN_SWAP is defined to 0")
|
||||
#pragma message("IT6635 EVB should be TX_PN_SWAP==1")
|
||||
#error ("Please define TX_PN_SWAP by your PCB layout.")
|
||||
|
||||
#else
|
||||
|
||||
#if TX_PN_SWAP
|
||||
#ifdef _SHOW_PRAGMA_MSG
|
||||
#pragma message("TX_PN_SWAP is pre-defined to 1")
|
||||
#endif
|
||||
#else
|
||||
#ifdef _SHOW_PRAGMA_MSG
|
||||
#pragma message("TX_PN_SWAP is pre-defined to 0")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DEFAULT_RS_IDX
|
||||
* :The default EQ when power on.
|
||||
*/
|
||||
#define DEFAULT_RS_IDX 4
|
||||
|
||||
/*
|
||||
* DEFAULT_PORT
|
||||
* :The default active port when power on.
|
||||
*/
|
||||
#define DEFAULT_PORT 0
|
||||
|
||||
// constant definition
|
||||
#define HPD_TOGGLE_TIMEOUT_400MS (27)
|
||||
#define HPD_TOGGLE_TIMEOUT_1SEC (100)
|
||||
#define HPD_TOGGLE_TIMEOUT_2SEC (20|(0x80))
|
||||
#define HPD_TOGGLE_TIMEOUT_3SEC (30|(0x80))
|
||||
|
||||
|
||||
|
||||
IT6635_RX_OPTIONS it66353_s_RxOpts = {
|
||||
0xC3, // u8 tag1;
|
||||
1, // u8 EnRxDDCBypass;
|
||||
0, // u8 EnRxPWR5VBypass;
|
||||
1, // u8 EnRxHPDBypass;
|
||||
1, // u8 TryFixedEQFirst;
|
||||
1, // u8 EnableAutoEQ;
|
||||
1, // u8 NonActivePortReplyHPD;
|
||||
0, // u8 DisableEdidRam;
|
||||
{DEFAULT_RS_IDX, DEFAULT_RS_IDX, DEFAULT_RS_IDX}, // u8 DefaultEQ[3];
|
||||
1, // u8 FixIncorrectHdmiEnc;
|
||||
0, // u8 HPDOutputInverse;
|
||||
HPD_TOGGLE_TIMEOUT_400MS, // u8 HPDTogglePeriod;
|
||||
1, // u8 TxOEAlignment;
|
||||
(u8)sizeof(IT6635_RX_OPTIONS), // u8 str_size;
|
||||
};
|
||||
|
||||
IT6635_TX_OPTIONS it66353_s_TxOpts = {
|
||||
0x3C, // u8 tag1;
|
||||
TX_PN_SWAP, // u8 EnTxPNSwap;
|
||||
TX_PN_SWAP, // u8 EnTxChSwap;
|
||||
0, // u8 EnTxVCLKInv;
|
||||
0, // u8 EnTxOutD1t;
|
||||
1, // u8 CopyEDIDFromSink;
|
||||
1, // u8 ParsePhysicalAddr;
|
||||
1, // u8 TurnOffTx5VWhenSwitchPort;
|
||||
(u8)sizeof(IT6635_TX_OPTIONS), // u8 str_size;
|
||||
};
|
||||
|
||||
IT6635_DEV_OPTION it66353_s_DevOpts = {
|
||||
0x5A, // u8 tag1;
|
||||
SWAddr, // u8 SwAddr;
|
||||
RXAddr, // u8 RxAddr;
|
||||
CECAddr, // u8 CecAddr;
|
||||
RXEDIDAddr, // u8 EdidAddr;
|
||||
// u8 EnCEC;
|
||||
0, // u8 ForceRxOn;
|
||||
1, // u8 RxAutoPowerDown;
|
||||
1, // u8 DoTxPowerDown;
|
||||
0, // u8 TxPowerDownWhileWaitingClock;
|
||||
(u8)sizeof(IT6635_DEV_OPTION), // u8 str_size;
|
||||
|
||||
};
|
||||
|
||||
u8 it66353_s_default_edid_port0[] = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
|
||||
0x26, 0x85, 0x35, 0x66, 0x01, 0x01, 0x01, 0x01,
|
||||
0x00, 0x19, 0x01, 0x03, 0x80, 0x80, 0x48, 0x78,
|
||||
0x0A, 0xDA, 0xFF, 0xA3, 0x58, 0x4A, 0xA2, 0x29,
|
||||
0x17, 0x49, 0x4B, 0x20, 0x08, 0x00, 0x31, 0x40,
|
||||
0x61, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0xE8,
|
||||
0x00, 0x30, 0xF2, 0x70, 0x5A, 0x80, 0xB0, 0x58,
|
||||
0x8A, 0x00, 0xBA, 0x88, 0x21, 0x00, 0x00, 0x1E,
|
||||
0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40,
|
||||
0x58, 0x2C, 0x45, 0x00, 0xBA, 0x88, 0x21, 0x00,
|
||||
0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x50,
|
||||
0x61, 0x6E, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x63,
|
||||
0x2D, 0x54, 0x56, 0x0A, 0x00, 0x00, 0x00, 0xFD,
|
||||
0x00, 0x17, 0x3D, 0x0F, 0x88, 0x3C, 0x00, 0x0A,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xF0,
|
||||
|
||||
0x02, 0x03, 0x43, 0xF0, 0x57, 0x10, 0x1F, 0x05,
|
||||
0x14, 0x20, 0x21, 0x22, 0x04, 0x13, 0x03, 0x12,
|
||||
0x07, 0x16, 0x5D, 0x5E, 0x5F, 0x62, 0x63, 0x64,
|
||||
0x61, 0x60, 0x66, 0x65, 0x23, 0x09, 0x07, 0x01,
|
||||
0x6E, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x38, 0x3C,
|
||||
0x2F, 0x00, 0x80, 0x01, 0x02, 0x03, 0x04, 0x67,
|
||||
0xD8, 0x5D, 0xC4, 0x01, 0x78, 0x80, 0x03, 0xE2,
|
||||
0x00, 0x4B, 0xE3, 0x05, 0x1F, 0x01, 0xE4, 0x0F,
|
||||
0x00, 0x00, 0x78, 0x56, 0x5E, 0x00, 0xA0, 0xA0,
|
||||
0xA0, 0x29, 0x50, 0x30, 0x20, 0x35, 0x00, 0xBA,
|
||||
0x88, 0x21, 0x00, 0x00, 0x1A, 0x66, 0x21, 0x56,
|
||||
0xAA, 0x51, 0x00, 0x1E, 0x30, 0x46, 0x8F, 0x33,
|
||||
0x00, 0xBA, 0x88, 0x21, 0x00, 0x00, 0x1E, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
|
||||
};
|
||||
|
||||
void it66353_options_init(void)
|
||||
{
|
||||
it66353_gdev.opts.rx_opt[0] = &it66353_s_RxOpts;
|
||||
it66353_gdev.opts.rx_opt[1] = &it66353_s_RxOpts;
|
||||
it66353_gdev.opts.rx_opt[2] = &it66353_s_RxOpts;
|
||||
it66353_gdev.opts.rx_opt[3] = &it66353_s_RxOpts;
|
||||
it66353_gdev.opts.active_rx_opt = it66353_gdev.opts.rx_opt[DEFAULT_PORT];
|
||||
it66353_gdev.opts.tx_opt = &it66353_s_TxOpts;
|
||||
it66353_gdev.opts.dev_opt = &it66353_s_DevOpts;
|
||||
it66353_gdev.vars.Rx_active_port = DEFAULT_PORT;
|
||||
|
||||
it66353_vars_init();
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
106
drivers/media/i2c/it66353/platform.h
Normal file
106
drivers/media/i2c/it66353/platform.h
Normal file
@@ -0,0 +1,106 @@
|
||||
// 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 _PLATFORM_H_
|
||||
#define _PLATFORM_H_
|
||||
/*
|
||||
* #ifndef u8
|
||||
* typedef unsigned char u8 ;
|
||||
* #endif
|
||||
* #ifndef u16
|
||||
* typedef unsigned short u16;
|
||||
* #endif
|
||||
* #ifndef u32
|
||||
* typedef unsigned long u32;
|
||||
* #endif
|
||||
* #ifndef __tick
|
||||
* typedef unsigned long __tick;
|
||||
* #endif
|
||||
*
|
||||
* #ifndef __cplusplus
|
||||
* #ifndef bool
|
||||
* typedef unsigned char bool ;
|
||||
* #endif
|
||||
* #endif
|
||||
*/
|
||||
|
||||
typedef unsigned long __tick;
|
||||
#define CONST const
|
||||
/*
|
||||
* #ifndef true
|
||||
* #define true 1
|
||||
* #endif
|
||||
*
|
||||
* #ifndef false
|
||||
* #define false 0
|
||||
* #endif
|
||||
*/
|
||||
/*
|
||||
* assign the print function
|
||||
*
|
||||
* #define pr_err dev_err
|
||||
* #define pr_info dev_info
|
||||
* #define pr_info2 dev_dbg
|
||||
*/
|
||||
|
||||
// ---------- for CEC
|
||||
|
||||
#define iTE_FALSE 0
|
||||
#define iTE_TRUE 1
|
||||
|
||||
#define WIN32
|
||||
|
||||
#ifdef _MCU_8051_
|
||||
typedef bit iTE_u1;
|
||||
#define _CODE code
|
||||
#define _CODE_3K code
|
||||
|
||||
#elif defined (WIN32)
|
||||
typedef int iTE_u1;
|
||||
#define _CODE const
|
||||
#define _CODE_3K const
|
||||
/*
|
||||
* #elif defined (_MCU_IT6350_)
|
||||
* typedef unsigned char iTE_u1;
|
||||
* #define _CODE __attribute__ ((section ("._OEM_BU1_RODATA ")))
|
||||
* #define _CODE_3K __attribute__ ((section ("._3K_RODATA ")))
|
||||
*/
|
||||
#elif defined (__WIN32__)
|
||||
typedef unsigned char iTE_u1;
|
||||
#define _CODE const
|
||||
#define _CODE_3K const
|
||||
|
||||
#else
|
||||
#error("Please define this section by your platform")
|
||||
typedef int iTE_u1;
|
||||
#define _CODE
|
||||
#define _CODE_3K
|
||||
#endif // _MCU_8051_
|
||||
|
||||
/*
|
||||
* output TXOE state on JP47 (GPC5)
|
||||
* by nVidia's clock detect request
|
||||
*/
|
||||
#define REPORT_TXOE_0(x) {GPDRC &= ~0x20; } //GPC5=0;
|
||||
#define REPORT_TXOE_1(x) {GPDRC |= 0x20; } //GPC5=1;
|
||||
|
||||
/*
|
||||
* typedef char iTE_s8, *iTE_ps8;
|
||||
* typedef unsigned char iTE_u8, *iTE_pu8;
|
||||
* typedef short iTE_s16, *iTE_ps16;
|
||||
* typedef unsigned short iTE_u16, *iTE_pu16;
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user