blob: d97d651e6aa45b4ce0d01b76916e95190c0de7f0 [file] [log] [blame]
/*
* drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/major.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
/* Local include */
#include "hdmi_rx_repeater.h"
#include "hdmi_rx_drv.h"
#include "hdmi_rx_hw.h"
#include "hdmi_rx_eq.h"
#include "hdmi_rx_wrapper.h"
#include "hdmi_rx_pktinfo.h"
#include "hdmi_rx_edid.h"
static int pll_unlock_cnt;
static int pll_unlock_max = 30;
static int pll_lock_cnt;
static int pll_lock_max = 2;
static int dwc_rst_wait_cnt;
static int dwc_rst_wait_cnt_max = 1;
static int sig_stable_cnt;
static int sig_stable_max = 10;
static int sig_stable_err_cnt;
static int sig_stable_err_max = 5;
static int max_err_cnt = 10;
static bool clk_debug;
static int hpd_wait_cnt;
/* increase time of hpd low, to avoid some source like */
/* MTK box/KaiboerH9 i2c communicate error */
static int hpd_wait_max = 40;
static int sig_unstable_cnt;
static int sig_unstable_max = 80;
bool vic_check_en;
bool dvi_check_en;
static int sig_unready_cnt;
static int sig_unready_max = 5;/* 10; */
static int pow5v_max_cnt = 3;
int rgb_quant_range;
int yuv_quant_range;
int it_content;
/* timing diff offset */
static int diff_pixel_th = 2;
static int diff_line_th = 10;
static int diff_frame_th = 40; /* (25hz-24hz)/2 = 50/100 */
static int err_dbg_cnt;
static int err_dbg_cnt_max = 500;
int force_vic;
uint32_t fsm_log_en;
uint32_t err_chk_en;
static int aud_sr_stb_max = 20;
/* used in other module */
static int audio_sample_rate;
module_param(audio_sample_rate, int, 0664);
MODULE_PARM_DESC(audio_sample_rate, "audio_sample_rate");
static int auds_rcv_sts;
module_param(auds_rcv_sts, int, 0664);
MODULE_PARM_DESC(auds_rcv_sts, "auds_rcv_sts");
static int audio_coding_type;
static int audio_channel_count;
int log_level = LOG_EN;/*| HDCP_LOG;*/
static bool auto_switch_off; /* only for hardware test */
int clk_unstable_cnt;
static int clk_unstable_max;
int clk_stable_cnt;
static int clk_stable_max = 3;
static int unnormal_wait_max = 200;
static int wait_no_sig_max = 600;
/* to inform ESM whether the cable is connected or not */
bool hpd_to_esm;
MODULE_PARM_DESC(hpd_to_esm, "\n hpd_to_esm\n");
module_param(hpd_to_esm, bool, 0664);
bool hdcp22_kill_esm;
MODULE_PARM_DESC(hdcp22_kill_esm, "\n hdcp22_kill_esm\n");
module_param(hdcp22_kill_esm, bool, 0664);
static int hdcp22_capable_sts = 0xff;
static bool esm_auth_fail_en;
MODULE_PARM_DESC(esm_auth_fail_en, "\n esm_auth_fail_en\n");
module_param(esm_auth_fail_en, bool, 0664);
static bool hdcp_mode_sel;
MODULE_PARM_DESC(hdcp_mode_sel, "\n hdcp_mode_sel\n");
module_param(hdcp_mode_sel, bool, 0664);
static int hdcp22_auth_sts = 0xff;
/*the esm reset flag for hdcp_rx22*/
static bool esm_reset_flag;
MODULE_PARM_DESC(esm_reset_flag, "\n esm_reset_flag\n");
module_param(esm_reset_flag, bool, 0664);
/* to inform ESM whether the cable is connected or not */
static bool video_stable_to_esm;
MODULE_PARM_DESC(video_stable_to_esm, "\n video_stable_to_esm\n");
module_param(video_stable_to_esm, bool, 0664);
static int enable_hdcp22_esm_log;
MODULE_PARM_DESC(enable_hdcp22_esm_log, "\n enable_hdcp22_esm_log\n");
module_param(enable_hdcp22_esm_log, int, 0664);
static bool esm_error_flag;
MODULE_PARM_DESC(esm_error_flag, "\n esm_error_flag\n");
module_param(esm_error_flag, bool, 0664);
static bool hdcp22_esm_reset2;
MODULE_PARM_DESC(hdcp22_esm_reset2, "\n hdcp22_esm_reset2\n");
module_param(hdcp22_esm_reset2, bool, 0664);
static bool hdcp22_stop_auth;
module_param(hdcp22_stop_auth, bool, 0664);
MODULE_PARM_DESC(hdcp22_stop_auth, "hdcp22_stop_auth");
static bool mute_kill_en;
MODULE_PARM_DESC(mute_kill_en, "\n mute_kill_en\n");
module_param(mute_kill_en, bool, 0664);
int hdcp14_on;
MODULE_PARM_DESC(hdcp14_on, "\n hdcp14_on\n");
module_param(hdcp14_on, int, 0664);
/*esm recovery mode for changing resolution & hdmi2.0*/
static int esm_recovery_mode = ESM_REC_MODE_TMDS;
module_param(esm_recovery_mode, int, 0664);
MODULE_PARM_DESC(esm_recovery_mode, "esm_recovery_mode");
int phy_retry_times = 1;
/* No need to judge frame rate while checking timing stable,as there are
* some out-spec sources whose framerate change a lot(e.g:59.7~60.16hz).
* Other brands of tv can support this,we also need to support.
*/
static int stable_check_lvl;
/* If dvd source received the frequent pulses on HPD line,
* It will sent a length of dirty audio data sometimes.it's TX's issues.
* Compared with other brands TV, delay 1.5S to avoid this noise.
*/
static int edid_update_delay = 150;
int skip_frame_cnt = 1;
static bool hdcp22_reauth_enable;
unsigned int edid_update_flag;
unsigned int downstream_hpd_flag;
static bool hdcp22_stop_auth_enable;
static bool hdcp22_esm_reset2_enable;
int sm_pause;
int pre_port = 0xff;
static int hdcp_none_wait_max = 100;
static int esd_phy_rst_cnt;
static int esd_phy_rst_max;
static int cec_dev_info;
struct rx_s rx;
void hdmirx_init_params(void)
{
if (rx.chip_id == CHIP_ID_TL1) {
clk_unstable_max = 10;
esd_phy_rst_max = 20;
stable_check_lvl = 0x7df;
pll_lock_max = 1;
} else {
clk_unstable_max = 200;
esd_phy_rst_max = 2;
stable_check_lvl = 0x17df;
pll_lock_max = 2;
}
}
void rx_hpd_to_esm_handle(struct work_struct *work)
{
cancel_delayed_work(&esm_dwork);
/* switch_set_state(&rx.hpd_sdev, 0x0); */
extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 0);
rx_pr("esm_hpd-0\n");
mdelay(80);
/* switch_set_state(&rx.hpd_sdev, 0x01); */
extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 1);
rx_pr("esm_hpd-1\n");
}
int cec_set_dev_info(uint8_t dev_idx)
{
cec_dev_info |= 1 << dev_idx;
if (dev_idx == 1)
hdcp_enc_mode = 1;
return 0;
}
EXPORT_SYMBOL(cec_set_dev_info);
/*
*func: irq tasklet
*param: flag:
* 0x01: audio irq
* 0x02: packet irq
*/
void rx_tasklet_handler(unsigned long arg)
{
struct rx_s *prx = (struct rx_s *)arg;
uint8_t irq_flag = prx->irq_flag;
prx->irq_flag = 0;
/*rx_pr("irq_flag = 0x%x\n", irq_flag);*/
if (irq_flag & IRQ_PACKET_FLAG)
rx_pkt_handler(PKT_BUFF_SET_FIFO);
/*pkt overflow or underflow*/
if (irq_flag & IRQ_PACKET_ERR)
hdmirx_packet_fifo_rst();
if (irq_flag & IRQ_AUD_FLAG)
hdmirx_audio_fifo_rst();
/*irq_flag = 0;*/
}
static int hdmi_rx_ctrl_irq_handler(void)
{
int error = 0;
/* unsigned i = 0; */
uint32_t intr_hdmi = 0;
uint32_t intr_md = 0;
uint32_t intr_pedc = 0;
uint32_t intr_aud_cec = 0;
/* uint32_t intr_aud_clk = 0; */
uint32_t intr_aud_fifo = 0;
uint32_t intr_hdcp22 = 0;
bool vsi_handle_flag = false;
bool drm_handle_flag = false;
bool emp_handle_flag = false;
uint32_t rx_top_intr_stat = 0;
bool irq_need_clr = 0;
/* clear interrupt quickly */
intr_hdmi =
hdmirx_rd_dwc(DWC_HDMI_ISTS) &
hdmirx_rd_dwc(DWC_HDMI_IEN);
if (intr_hdmi != 0)
hdmirx_wr_dwc(DWC_HDMI_ICLR, intr_hdmi);
intr_md =
hdmirx_rd_dwc(DWC_MD_ISTS) &
hdmirx_rd_dwc(DWC_MD_IEN);
if (intr_md != 0)
hdmirx_wr_dwc(DWC_MD_ICLR, intr_md);
intr_pedc =
hdmirx_rd_dwc(DWC_PDEC_ISTS) &
hdmirx_rd_dwc(DWC_PDEC_IEN);
if (intr_pedc != 0)
hdmirx_wr_dwc(DWC_PDEC_ICLR, intr_pedc);
intr_aud_fifo =
hdmirx_rd_dwc(DWC_AUD_FIFO_ISTS) &
hdmirx_rd_dwc(DWC_AUD_FIFO_IEN);
if (intr_aud_fifo != 0)
hdmirx_wr_dwc(DWC_AUD_FIFO_ICLR, intr_aud_fifo);
if (hdcp22_on) {
intr_hdcp22 =
hdmirx_rd_dwc(DWC_HDMI2_ISTS) &
hdmirx_rd_dwc(DWC_HDMI2_IEN);
}
if (is_meson_txl_cpu()) {
intr_aud_cec =
hdmirx_rd_dwc(DWC_AUD_CEC_ISTS) &
hdmirx_rd_dwc(DWC_AUD_CEC_IEN);
if (intr_aud_cec != 0) {
cecb_irq_handle();
hdmirx_wr_dwc(DWC_AUD_CEC_ICLR, intr_aud_cec);
}
}
if (intr_hdcp22 != 0) {
hdmirx_wr_dwc(DWC_HDMI2_ICLR, intr_hdcp22);
skip_frame(skip_frame_cnt);
if (log_level & HDCP_LOG)
rx_pr("intr=%#x\n", intr_hdcp22);
switch (intr_hdcp22) {
case _BIT(0):
hdcp22_capable_sts = HDCP22_AUTH_STATE_CAPABLE;
rx.hdcp.hdcp_version = HDCP_VER_22;
break;
case _BIT(1):
hdcp22_capable_sts = HDCP22_AUTH_STATE_NOT_CAPABLE;
break;
case _BIT(2):
hdcp22_auth_sts = HDCP22_AUTH_STATE_LOST;
break;
case _BIT(3):
hdcp22_auth_sts = HDCP22_AUTH_STATE_SUCCESS;
break;
case _BIT(4):
hdcp22_auth_sts = HDCP22_AUTH_STATE_FAILED;
break;
default:
break;
}
}
if (rx.chip_id != CHIP_ID_TL1) {
rx_top_intr_stat = hdmirx_rd_top(TOP_INTR_STAT);
if (rx_top_intr_stat & _BIT(31))
irq_need_clr = 1;
}
/* check hdmi open status before dwc isr */
if (!rx.open_fg) {
if (irq_need_clr)
error = 1;
if (log_level & 0x1000)
rx_pr("[isr] ignore dwc isr ---\n");
return error;
}
if (intr_hdmi != 0) {
if (rx_get_bits(intr_hdmi, AKSV_RCV) != 0) {
/*if (log_level & HDCP_LOG)*/
rx_pr("[*aksv*\n");
rx.hdcp.hdcp_version = HDCP_VER_14;
if (hdmirx_repeat_support())
rx_start_repeater_auth();
}
}
if (intr_md != 0) {
if (rx_get_bits(intr_md, md_ists_en) != 0) {
if (log_level & 0x100)
rx_pr("md_ists:%x\n", intr_md);
}
}
if (intr_pedc != 0) {
if (rx_get_bits(intr_pedc, DVIDET | AVI_CKS_CHG) != 0) {
if (log_level & 0x400)
rx_pr("[irq] AVI_CKS_CHG\n");
}
if (rx_get_bits(intr_pedc, VSI_RCV) != 0) {
if (log_level & 0x400)
rx_pr("[irq] VSI_RCV\n");
vsi_handle_flag = true;
}
if (rx_get_bits(intr_pedc, VSI_CKS_CHG) != 0) {
if (log_level & 0x400)
rx_pr("[irq] VSI_CKS_CHG\n");
}
if (rx_get_bits(intr_pedc, PD_FIFO_START_PASS) != 0) {
if (log_level & 0x200)
rx_pr("[irq] FIFO START\n");
rx.irq_flag |= IRQ_PACKET_FLAG;
}
if (rx_get_bits(intr_pedc, _BIT(1)) != 0) {
if (log_level & 0x200)
rx_pr("[irq] FIFO MAX\n");
}
if (rx_get_bits(intr_pedc, _BIT(0)) != 0) {
if (log_level & 0x200)
rx_pr("[irq] FIFO MIN\n");
}
if (rx.chip_id == CHIP_ID_TL1) {
if (rx_get_bits(intr_pedc,
_BIT(9)) != 0) {
if (log_level & 0x400)
rx_pr("[irq] EMP_RCV %#x\n",
intr_pedc);
emp_handle_flag = true;
} else if (rx_get_bits(intr_pedc,
DRM_RCV_EN_TXLX) != 0) {
if (log_level & 0x400)
rx_pr("[irq] DRM_RCV_EN %#x\n",
intr_pedc);
drm_handle_flag = true;
}
} else if (rx.chip_id == CHIP_ID_TXLX) {
if (rx_get_bits(intr_pedc,
DRM_RCV_EN_TXLX) != 0) {
if (log_level & 0x400)
rx_pr("[irq] DRM_RCV_EN %#x\n",
intr_pedc);
drm_handle_flag = true;
}
} else {
if (rx_get_bits(intr_pedc,
DRM_RCV_EN) != 0) {
if (log_level & 0x400)
rx_pr("[irq] DRM_RCV_EN %#x\n",
intr_pedc);
drm_handle_flag = true;
}
}
if (rx_get_bits(intr_pedc, PD_FIFO_OVERFL) != 0) {
if (log_level & 0x200)
rx_pr("[irq] PD_FIFO_OVERFL\n");
rx.irq_flag |= IRQ_PACKET_ERR;
/*hdmirx_packet_fifo_rst();*/
}
if (rx_get_bits(intr_pedc, PD_FIFO_UNDERFL) != 0) {
if (log_level & 0x200)
rx_pr("[irq] PD_FIFO_UNDFLOW\n");
rx.irq_flag |= IRQ_PACKET_ERR;
/*hdmirx_packet_fifo_rst();*/
}
}
if (intr_aud_fifo != 0) {
if (rx_get_bits(intr_aud_fifo, OVERFL) != 0) {
if (log_level & 0x100)
rx_pr("[irq] OVERFL\n");
rx.irq_flag |= IRQ_AUD_FLAG;
/* when afifo overflow in multi-channel case(VG-877),
* then store all subpkts into afifo, 8ch in and 8ch out
*/
if (rx.aud_info.auds_layout)
rx_afifo_store_all_subpkt(true);
else
rx_afifo_store_all_subpkt(false);
//if (rx.aud_info.real_sr != 0)
//error |= hdmirx_audio_fifo_rst();
}
if (rx_get_bits(intr_aud_fifo, UNDERFL) != 0) {
if (log_level & 0x100)
rx_pr("[irq] UNDERFL\n");
rx.irq_flag |= IRQ_AUD_FLAG;
rx_afifo_store_all_subpkt(false);
//if (rx.aud_info.real_sr != 0)
//error |= hdmirx_audio_fifo_rst();
}
}
if (vsi_handle_flag)
rx_pkt_handler(PKT_BUFF_SET_VSI);
if (drm_handle_flag)
rx_pkt_handler(PKT_BUFF_SET_DRM);
if (emp_handle_flag)
rx_pkt_handler(PKT_BUFF_SET_EMP);
if (rx.irq_flag)
tasklet_schedule(&rx_tasklet);
if (irq_need_clr)
error = 1;
return error;
}
irqreturn_t irq_handler(int irq, void *params)
{
int error = 0;
unsigned long hdmirx_top_intr_stat;
if (params == 0) {
rx_pr("%s: %s\n",
__func__,
"RX IRQ invalid parameter");
return IRQ_HANDLED;
}
reisr:hdmirx_top_intr_stat = hdmirx_rd_top(TOP_INTR_STAT);
hdmirx_wr_top(TOP_INTR_STAT_CLR, hdmirx_top_intr_stat);
/* modify interrupt flow for isr loading */
/* top interrupt handler */
if (rx.chip_id == CHIP_ID_TL1) {
if (hdmirx_top_intr_stat & (1 << 29))
if (log_level & 0x100)
rx_pr("[isr] sqofclk_fall\n");
if (hdmirx_top_intr_stat & (1 << 28))
if (log_level & 0x100)
rx_pr("[isr] sqofclk_rise\n");
if (hdmirx_top_intr_stat & (1 << 27))
if (log_level & 0x400)
rx_pr("[isr] DE rise edge.\n");
if (hdmirx_top_intr_stat & (1 << 26)) {
rx_emp_lastpkt_done_irq();
if (log_level & 0x400)
rx_pr("[isr] last_emp_done\n");
}
if (hdmirx_top_intr_stat & (1 << 25)) {
rx_emp_field_done_irq();
if (log_level & 0x400)
rx_pr("[isr] emp_field_done\n");
}
if (hdmirx_top_intr_stat & (1 << 24))
if (log_level & 0x100)
rx_pr("[isr] tmds_align_stable_chg\n");
if (hdmirx_top_intr_stat & (1 << 23))
if (log_level & 0x100)
rx_pr("[isr] meter_stable_chg_cable\n");
}
if (hdmirx_top_intr_stat & (1 << 13))
rx_pr("[isr] auth rise\n");
if (hdmirx_top_intr_stat & (1 << 14))
rx_pr("[isr] auth fall\n");
if (hdmirx_top_intr_stat & (1 << 15))
rx_pr("[isr] enc rise\n");
if (hdmirx_top_intr_stat & (1 << 16))
rx_pr("[isr] enc fall\n");
/* must clear ip interrupt quickly */
if (rx.chip_id == CHIP_ID_TL1) {
hdmirx_top_intr_stat &= 0x1;
} else {
hdmirx_top_intr_stat &= (~(1 << 30));
}
if (hdmirx_top_intr_stat) {
error = hdmi_rx_ctrl_irq_handler();
if (error < 0) {
if (error != -EPERM) {
rx_pr("%s: RX IRQ handler %d\n",
__func__,
error);
}
}
}
if (rx.chip_id != CHIP_ID_TL1) {
if (error == 1)
goto reisr;
} else {
hdmirx_top_intr_stat = hdmirx_rd_top(TOP_INTR_STAT);
hdmirx_top_intr_stat &= 0x1;
if (hdmirx_top_intr_stat) {
if (log_level & ERR_LOG)
rx_pr("\n irq_miss");
goto reisr;
}
}
/* check the ip interrupt again */
/*hdmirx_top_intr_stat = hdmirx_rd_top(TOP_INTR_STAT);
*if (hdmirx_top_intr_stat & (1 << 31)) {
* if (log_level & 0x100)
* rx_pr("[isr] need clear ip irq---\n");
* goto reisr;
*
*}
*/
return IRQ_HANDLED;
}
static const uint32_t sr_tbl[][2] = {
{32000, 3000},
{44100, 2000},
{48000, 2000},
{88200, 3000},
{96000, 3000},
{176400, 3000},
{192000, 3000},
{0, 0}
};
static bool check_real_sr_change(void)
{
uint8_t i;
bool ret = false;
/* note: if arc is missmatch with LUT, then return 0 */
uint32_t ret_sr = 0;
for (i = 0; sr_tbl[i][0] != 0; i++) {
if (abs(rx.aud_info.arc - sr_tbl[i][0]) < sr_tbl[i][1]) {
ret_sr = sr_tbl[i][0];
break;
}
}
if (ret_sr != rx.aud_info.real_sr) {
rx.aud_info.real_sr = ret_sr;
ret = true;
if (log_level & AUDIO_LOG)
dump_state(RX_DUMP_AUDIO);
}
return ret;
}
static const struct freq_ref_s freq_ref[] = {
/* interlace 420 3d hac vac index */
/* 420mode */
{0, 3, 0, 1920, 2160, HDMI_2160p50_16x9_Y420},
{0, 3, 0, 2048, 2160, HDMI_4096p50_256x135_Y420},
{0, 3, 0, 960, 1080, HDMI_1080p_420},
/* interlace */
/* {1, 0, 0, 720, 240, HDMI_720x480i}, */
{1, 0, 0, 1440, 240, HDMI_480i60},
/* {1, 0, 0, 720, 288, HDMI_720x576i}, */
{1, 0, 0, 1440, 288, HDMI_576i50},
{1, 0, 0, 1920, 540, HDMI_1080i50},
{1, 0, 2, 1920, 1103, HDMI_1080i_ALTERNATIVE},
{1, 0, 1, 1920, 2228, HDMI_1080i_FRAMEPACKING},
{0, 0, 0, 1440, 240, HDMI_1440x240p60},
{0, 0, 0, 2880, 240, HDMI_2880x240p60},
{0, 0, 0, 1440, 288, HDMI_1440x288p50},
{0, 0, 0, 2880, 288, HDMI_2880x288p50},
{0, 0, 0, 720, 480, HDMI_480p60},
{0, 0, 0, 1440, 480, HDMI_1440x480p60},
{0, 0, 1, 720, 1005, HDMI_480p_FRAMEPACKING},
{0, 0, 0, 720, 576, HDMI_576p50},
{0, 0, 0, 1440, 576, HDMI_1440x576p50},
{0, 0, 1, 720, 1201, HDMI_576p_FRAMEPACKING},
{0, 0, 0, 1280, 720, HDMI_720p50},
{0, 0, 1, 1280, 1470, HDMI_720p_FRAMEPACKING},
{0, 0, 0, 1920, 1080, HDMI_1080p50},
{0, 0, 2, 1920, 2160, HDMI_1080p_ALTERNATIVE},
{0, 0, 1, 1920, 2205, HDMI_1080p_FRAMEPACKING},
{1, 0, 0, 2880, 240, HDMI_2880x480i60},
{1, 0, 0, 2880, 288, HDMI_2880x576i50},
{0, 0, 0, 2880, 480, HDMI_2880x480p60},
{0, 0, 0, 2880, 576, HDMI_2880x576p50},
/* vesa format*/
{0, 0, 0, 640, 480, HDMI_640x480p60},
{0, 0, 0, 720, 400, HDMI_720_400},
{0, 0, 0, 800, 600, HDMI_800_600},
{0, 0, 0, 1024, 768, HDMI_1024_768},
{0, 0, 0, 1280, 768, HDMI_1280_768},
{0, 0, 0, 1280, 800, HDMI_1280_800},
{0, 0, 0, 1280, 960, HDMI_1280_960},
{0, 0, 0, 1280, 1024, HDMI_1280_1024},
{0, 0, 0, 1360, 768, HDMI_1360_768},
{0, 0, 0, 1366, 768, HDMI_1366_768},
{0, 0, 0, 1440, 900, HDMI_1440_900},
{0, 0, 0, 1400, 1050, HDMI_1400_1050},
{0, 0, 0, 1600, 900, HDMI_1600_900},
{0, 0, 0, 1600, 1200, HDMI_1600_1200},
{0, 0, 0, 1680, 1050, HDMI_1680_1050},
{0, 0, 0, 1920, 1200, HDMI_1920_1200},
/* 4k2k mode */
{0, 0, 0, 3840, 2160, HDMI_2160p24_16x9},
{0, 0, 0, 4096, 2160, HDMI_4096p24_256x135},
{0, 0, 0, 2560, 1440, HDMI_2560_1440},
{0, 0, 1, 2560, 3488, HDMI_2560_1440},
{0, 0, 2, 2560, 2986, HDMI_2560_1440},
/* for AG-506 */
{0, 0, 0, 720, 483, HDMI_480p60},
};
static bool fmt_vic_abnormal(void)
{
/* if format is unknown or unsupported after
* timing match, but TX send normal VIC, then
* abnormal format is detected.
*/
if ((rx.pre.sw_vic == HDMI_UNKNOWN) ||
(rx.pre.sw_vic == HDMI_UNSUPPORT)) {
if (log_level & VIDEO_LOG)
rx_pr("fmt_vic_abnormal\n");
return true;
} else
return false;
}
enum tvin_sig_fmt_e hdmirx_hw_get_fmt(void)
{
enum tvin_sig_fmt_e fmt = TVIN_SIG_FMT_NULL;
enum hdmi_vic_e vic = HDMI_UNKNOWN;
if (fmt_vic_abnormal())
vic = rx.pre.hw_vic;
else
vic = rx.pre.sw_vic;
if (force_vic)
vic = force_vic;
switch (vic) {
case HDMI_640x480p60:
fmt = TVIN_SIG_FMT_HDMI_640X480P_60HZ;
break;
case HDMI_480p60: /*2 */
case HDMI_480p60_16x9: /*3 */
case HDMI_480p120: /* 48 */
case HDMI_480p120_16x9: /* 49 */
case HDMI_480p240: /* 56 */
case HDMI_480p240_16x9: /* 57 */
fmt = TVIN_SIG_FMT_HDMI_720X480P_60HZ;
break;
case HDMI_1440x480p60: /* 14 */
case HDMI_1440x480p60_16x9: /* 15 */
fmt = TVIN_SIG_FMT_HDMI_1440X480P_60HZ;
break;
case HDMI_480p_FRAMEPACKING:
fmt = TVIN_SIG_FMT_HDMI_720X480P_60HZ_FRAME_PACKING;
break;
case HDMI_720p24: /* 60 */
case HDMI_720p25: /* 61 */
case HDMI_720p30: /* 62 */
case HDMI_720p50: /* 19 */
case HDMI_720p60: /* 4 */
case HDMI_720p100: /* 41 */
case HDMI_720p120: /* 47 */
case HDMI_720p24_64x27: /* 65 */
case HDMI_720p25_64x27: /* 66 */
case HDMI_720p30_64x27: /* 67 */
case HDMI_720p50_64x27: /* 68 */
case HDMI_720p60_64x27: /* 69 */
case HDMI_720p100_64x27: /* 70 */
case HDMI_720p120_64x27: /* 71 */
fmt = TVIN_SIG_FMT_HDMI_1280X720P_60HZ;
break;
case HDMI_720p_FRAMEPACKING:
fmt = TVIN_SIG_FMT_HDMI_1280X720P_60HZ_FRAME_PACKING;
break;
case HDMI_1080i50: /* 20 */
case HDMI_1080i100: /* 40 */
case HDMI_1080i60: /* 5 */
case HDMI_1080i120: /* 46 */
fmt = TVIN_SIG_FMT_HDMI_1920X1080I_60HZ;
break;
case HDMI_1080i_FRAMEPACKING:
fmt = TVIN_SIG_FMT_HDMI_1920X1080I_60HZ_FRAME_PACKING;
break;
case HDMI_1080i_ALTERNATIVE:
fmt = TVIN_SIG_FMT_HDMI_1920X1080I_60HZ_ALTERNATIVE;
break;
case HDMI_480i60: /* 6 */
case HDMI_480i60_16x9: /* 7 */
case HDMI_480i120: /* 50 */
case HDMI_480i120_16x9: /* 51 */
case HDMI_480i240: /* 58 */
case HDMI_480i240_16x9: /* 59 */
fmt = TVIN_SIG_FMT_HDMI_1440X480I_60HZ;
break;
case HDMI_1080p24: /* 32 */
case HDMI_1080p24_64x27: /* 72 */
case HDMI_1080p25: /* 33 */
case HDMI_1080p25_64x27: /* 73 */
case HDMI_1080p30: /* 34 */
case HDMI_1080p30_64x27: /* 74 */
case HDMI_1080p50: /* 31 */
case HDMI_1080p60: /* 16 */
case HDMI_1080p50_64x27: /* 75 */
case HDMI_1080p60_64x27: /* 76 */
case HDMI_1080p100: /* 64 */
case HDMI_1080p120: /* 63 */
case HDMI_1080p100_64x27: /* 77 */
case HDMI_1080p120_64x27: /* 78 */
case HDMI_1080p_420:
fmt = TVIN_SIG_FMT_HDMI_1920X1080P_60HZ;
break;
case HDMI_1080p_FRAMEPACKING:
fmt = TVIN_SIG_FMT_HDMI_1920X1080P_24HZ_FRAME_PACKING;
break;
case HDMI_1080p_ALTERNATIVE:
fmt = TVIN_SIG_FMT_HDMI_1920X1080P_24HZ_ALTERNATIVE;
break;
case HDMI_576p50: /* 17 */
case HDMI_576p50_16x9: /* 18 */
case HDMI_576p100: /* 42 */
case HDMI_576p100_16x9: /* 43 */
case HDMI_576p200: /* 52 */
case HDMI_576p200_16x9: /* 53 */
fmt = TVIN_SIG_FMT_HDMI_720X576P_50HZ;
break;
case HDMI_1440x576p50: /* 29 */
case HDMI_1440x576p50_16x9: /* 30 */
fmt = TVIN_SIG_FMT_HDMI_1440X576P_50HZ;
break;
case HDMI_576p_FRAMEPACKING:
fmt = TVIN_SIG_FMT_HDMI_720X576P_50HZ_FRAME_PACKING;
break;
case HDMI_576i50: /* 21 */
case HDMI_576i50_16x9: /* 22 */
case HDMI_576i100: /* 44 */
case HDMI_576i100_16x9: /* 45 */
case HDMI_576i200: /* 54 */
case HDMI_576i200_16x9: /* 55 */
fmt = TVIN_SIG_FMT_HDMI_1440X576I_50HZ;
break;
case HDMI_1440x240p60: /* 8 */
case HDMI_1440x240p60_16x9: /* 9 */
fmt = TVIN_SIG_FMT_HDMI_1440X240P_60HZ;
break;
case HDMI_2880x240p60: /* 12 */
case HDMI_2880x240p60_16x9: /* 13 */
fmt = TVIN_SIG_FMT_HDMI_2880X240P_60HZ;
break;
case HDMI_1440x288p50: /* 23 */
case HDMI_1440x288p50_16x9: /* 24 */
fmt = TVIN_SIG_FMT_HDMI_1440X288P_50HZ;
break;
case HDMI_2880x288p50: /* 27 */
case HDMI_2880x288p50_16x9: /* 28 */
fmt = TVIN_SIG_FMT_HDMI_2880X288P_50HZ;
break;
case HDMI_2880x480i60: /* 10 */
case HDMI_2880x480i60_16x9: /* 11 */
fmt = TVIN_SIG_FMT_HDMI_2880X480I_60HZ;
break;
case HDMI_2880x576i50: /* 25 */
case HDMI_2880x576i50_16x9: /* 26 */
fmt = TVIN_SIG_FMT_HDMI_2880X576I_50HZ;
break;
case HDMI_2880x480p60: /* 35 */
case HDMI_2880x480p60_16x9: /* 36 */
fmt = TVIN_SIG_FMT_HDMI_2880X480P_60HZ;
break;
case HDMI_2880x576p50: /* 37 */
case HDMI_2880x576p50_16x9: /* 38 */
fmt = TVIN_SIG_FMT_HDMI_2880X576P_50HZ;
break;
case HDMI_1080i50_1250: /* 39 */
fmt = TVIN_SIG_FMT_HDMI_1920X1080I_50HZ_B;
break;
/* VESA mode*/
case HDMI_800_600:
fmt = TVIN_SIG_FMT_HDMI_800X600_00HZ;
break;
case HDMI_1024_768:
fmt = TVIN_SIG_FMT_HDMI_1024X768_00HZ;
break;
case HDMI_720_400:
fmt = TVIN_SIG_FMT_HDMI_720X400_00HZ;
break;
case HDMI_1280_768:
fmt = TVIN_SIG_FMT_HDMI_1280X768_00HZ;
break;
case HDMI_1280_800:
fmt = TVIN_SIG_FMT_HDMI_1280X800_00HZ;
break;
case HDMI_1280_960:
fmt = TVIN_SIG_FMT_HDMI_1280X960_00HZ;
break;
case HDMI_1280_1024:
fmt = TVIN_SIG_FMT_HDMI_1280X1024_00HZ;
break;
case HDMI_1360_768:
fmt = TVIN_SIG_FMT_HDMI_1360X768_00HZ;
break;
case HDMI_1366_768:
fmt = TVIN_SIG_FMT_HDMI_1366X768_00HZ;
break;
case HDMI_1600_1200:
fmt = TVIN_SIG_FMT_HDMI_1600X1200_00HZ;
break;
case HDMI_1600_900:
fmt = TVIN_SIG_FMT_HDMI_1600X900_60HZ;
break;
case HDMI_1920_1200:
fmt = TVIN_SIG_FMT_HDMI_1920X1200_00HZ;
break;
case HDMI_1440_900:
fmt = TVIN_SIG_FMT_HDMI_1440X900_00HZ;
break;
case HDMI_1400_1050:
fmt = TVIN_SIG_FMT_HDMI_1400X1050_00HZ;
break;
case HDMI_1680_1050:
fmt = TVIN_SIG_FMT_HDMI_1680X1050_00HZ;
break;
case HDMI_2160p24_16x9:
case HDMI_2160p25_16x9:
case HDMI_2160p30_16x9:
case HDMI_2160p50_16x9:
case HDMI_2160p60_16x9:
case HDMI_2160p24_64x27:
case HDMI_2160p25_64x27:
case HDMI_2160p30_64x27:
case HDMI_2160p50_64x27:
case HDMI_2160p60_64x27:
case HDMI_2160p50_16x9_Y420:
case HDMI_2160p60_16x9_Y420:
case HDMI_2160p50_64x27_Y420:
case HDMI_2160p60_64x27_Y420:
if (en_4k_timing)
fmt = TVIN_SIG_FMT_HDMI_3840_2160_00HZ;
else
fmt = TVIN_SIG_FMT_NULL;
break;
case HDMI_4096p24_256x135:
case HDMI_4096p25_256x135:
case HDMI_4096p30_256x135:
case HDMI_4096p50_256x135:
case HDMI_4096p60_256x135:
case HDMI_4096p50_256x135_Y420:
case HDMI_4096p60_256x135_Y420:
if (en_4k_timing)
fmt = TVIN_SIG_FMT_HDMI_4096_2160_00HZ;
else
fmt = TVIN_SIG_FMT_NULL;
break;
case HDMI_2560_1440:
fmt = TVIN_SIG_FMT_HDMI_1920X1200_00HZ;
break;
default:
break;
}
return fmt;
}
bool rx_is_sig_ready(void)
{
if ((rx.state == FSM_SIG_READY) ||
(force_vic))
return true;
else
return false;
}
bool rx_is_nosig(void)
{
if (force_vic)
return false;
return rx.no_signal;
}
/*
* check timing info
*/
static bool rx_is_timing_stable(void)
{
bool ret = true;
uint32_t ch0 = 0, ch1 = 0, ch2 = 0;
if (stable_check_lvl & TMDS_VALID_EN) {
if (!is_tmds_valid()) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("TMDS invalid\n");
}
}
if (stable_check_lvl & HACTIVE_EN) {
if (diff(rx.cur.hactive, rx.pre.hactive) > diff_pixel_th) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("hactive(%d=>%d),",
rx.pre.hactive,
rx.cur.hactive);
}
}
if (stable_check_lvl & VACTIVE_EN) {
if (diff(rx.cur.vactive, rx.pre.vactive) > diff_line_th) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("vactive(%d=>%d),",
rx.pre.vactive,
rx.cur.vactive);
}
}
if (stable_check_lvl & HTOTAL_EN) {
if (diff(rx.cur.htotal, rx.pre.htotal) > diff_pixel_th) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("htotal(%d=>%d),",
rx.pre.htotal,
rx.cur.htotal);
}
}
if (stable_check_lvl & VTOTAL_EN) {
if (diff(rx.cur.vtotal, rx.pre.vtotal) > diff_line_th) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("vtotal(%d=>%d),",
rx.pre.vtotal,
rx.cur.vtotal);
}
}
if (stable_check_lvl & COLSPACE_EN) {
if (rx.pre.colorspace != rx.cur.colorspace) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("colorspace(%d=>%d),",
rx.pre.colorspace,
rx.cur.colorspace);
}
}
if (stable_check_lvl & REFRESH_RATE_EN) {
if (diff(rx.pre.frame_rate, rx.cur.frame_rate)
> diff_frame_th) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("frame_rate(%d=>%d),",
rx.pre.frame_rate,
rx.cur.frame_rate);
}
}
if (stable_check_lvl & REPEAT_EN) {
if ((rx.pre.repeat != rx.cur.repeat) &&
(stable_check_lvl & REPEAT_EN)) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("repeat(%d=>%d),",
rx.pre.repeat,
rx.cur.repeat);
}
}
if (stable_check_lvl & DVI_EN) {
if (rx.pre.hw_dvi != rx.cur.hw_dvi) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("dvi(%d=>%d),",
rx.pre.hw_dvi,
rx.cur.hw_dvi);
}
}
if (stable_check_lvl & INTERLACED_EN) {
if (rx.pre.interlaced != rx.cur.interlaced) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("interlaced(%d=>%d),",
rx.pre.interlaced,
rx.cur.interlaced);
}
}
if (stable_check_lvl & COLOR_DEP_EN) {
if (rx.pre.colordepth != rx.cur.colordepth) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("colordepth(%d=>%d),",
rx.pre.colordepth,
rx.cur.colordepth);
}
}
if (stable_check_lvl & ERR_CNT_EN) {
rx_get_error_cnt(&ch0, &ch1, &ch2);
if ((ch0 + ch1 + ch2) > max_err_cnt) {
if (sig_stable_err_cnt++ > sig_stable_err_max) {
rx_pr("warning: more err counter\n");
sig_stable_err_cnt = 0;
/*phy setting is fail, need reset phy*/
sig_unstable_cnt = sig_unstable_max;
rx.phy.cable_clk = 0;
}
ret = false;
}
}
if ((ret == false) && (log_level & VIDEO_LOG))
rx_pr("\n");
if (force_vic)
ret = true;
return ret;
}
static int get_timing_fmt(void)
{
int i;
int size = sizeof(freq_ref)/sizeof(struct freq_ref_s);
rx.pre.sw_vic = HDMI_UNKNOWN;
rx.pre.sw_dvi = 0;
rx.pre.sw_fp = 0;
rx.pre.sw_alternative = 0;
for (i = 0; i < size; i++) {
if (abs(rx.pre.hactive - freq_ref[i].hactive) > diff_pixel_th)
continue;
if ((abs(rx.pre.vactive - freq_ref[i].vactive)) > diff_line_th)
continue;
if ((rx.pre.colorspace != freq_ref[i].cd420) &&
(freq_ref[i].cd420 != 0))
continue;
if (freq_ref[i].interlace != rx.pre.interlaced)
continue;
break;
}
if (i == size) {
/* if format is not matched, sw_vic will be UNSUPPORT */
rx.pre.sw_vic = HDMI_UNSUPPORT;
return i;
}
rx.pre.sw_vic = freq_ref[i].vic;
rx.pre.sw_dvi = rx.pre.hw_dvi;
return i;
}
static void set_fsm_state(enum fsm_states_e sts)
{
rx.state = sts;
}
static void signal_status_init(void)
{
hpd_wait_cnt = 0;
pll_unlock_cnt = 0;
pll_lock_cnt = 0;
sig_unstable_cnt = 0;
sig_stable_cnt = 0;
sig_unstable_cnt = 0;
sig_unready_cnt = 0;
/*rx.wait_no_sig_cnt = 0;*/
/* rx.no_signal = false; */
//rx.pre_state = 0;
/* audio */
audio_sample_rate = 0;
audio_coding_type = 0;
audio_channel_count = 0;
auds_rcv_sts = 0;
rx.aud_sr_stable_cnt = 0;
rx.aud_sr_unstable_cnt = 0;
//rx_aud_pll_ctl(0);
rx_set_eq_run_state(E_EQ_START);
rx.err_rec_mode = ERR_REC_EQ_RETRY;
rx.err_code = ERR_NONE;
rx_irq_en(false);
if (hdcp22_on) {
if (esm_recovery_mode == ESM_REC_MODE_TMDS)
rx_esm_tmdsclk_en(false);
esm_set_stable(false);
}
set_scdc_cfg(1, 0);
rx.state = FSM_INIT;
/*if (hdcp22_on)*/
/*esm_set_stable(0);*/
rx.hdcp.hdcp_version = HDCP_VER_NONE;
rx.skip = 0;
}
void packet_update(void)
{
/*rx_getaudinfo(&rx.aud_info);*/
rgb_quant_range = rx.cur.rgb_quant_range;
yuv_quant_range = rx.cur.yuv_quant_range;
it_content = rx.cur.it_content;
auds_rcv_sts = rx.aud_info.aud_packet_received;
audio_sample_rate = rx.aud_info.real_sr;
audio_coding_type = rx.aud_info.coding_type;
audio_channel_count = rx.aud_info.channel_count;
}
void hdmirx_hdcp22_reauth(void)
{
if (hdcp22_reauth_enable) {
esm_auth_fail_en = 1;
hdcp22_auth_sts = 0xff;
}
}
void monitor_hdcp22_sts(void)
{
/*if the auth lost after the success of authentication*/
if ((hdcp22_capable_sts == HDCP22_AUTH_STATE_CAPABLE) &&
((hdcp22_auth_sts == HDCP22_AUTH_STATE_LOST) ||
(hdcp22_auth_sts == HDCP22_AUTH_STATE_FAILED))) {
hdmirx_hdcp22_reauth();
/*rx_pr("\n auth lost force hpd rst\n");*/
}
}
void rx_dwc_reset(void)
{
if (log_level & VIDEO_LOG)
rx_pr("rx_dwc_reset\n");
/*
* hdcp14 sts only be cleared by
* 1. hdmi swreset
* 2. new AKSV is received
*/
if ((rx.hdcp.hdcp_version == HDCP_VER_NONE) &&
(rx_get_hdcp14_sts() != 0))
rx_sw_reset(2);
else
rx_sw_reset(1);
rx_irq_en(true);
/* for hdcp1.4 interact very early cases, don't do
* esm reset to avoid interaction be interferenced.
*/
if (hdcp22_on &&
(rx.hdcp.hdcp_version != HDCP_VER_14)) {
if (esm_recovery_mode == ESM_REC_MODE_TMDS)
rx_esm_tmdsclk_en(true);
esm_set_stable(true);
if (rx.hdcp.hdcp_version == HDCP_VER_22)
hdmirx_hdcp22_reauth();
}
hdmirx_audio_fifo_rst();
hdmirx_packet_fifo_rst();
}
bool rx_hpd_keep_low(void)
{
bool ret = false;
if (downstream_hpd_flag) {
if (hpd_wait_cnt <= hpd_wait_max*5)
ret = true;
} else {
if (hpd_wait_cnt <= hpd_wait_max)
ret = true;
}
return ret;
}
int rx_get_cur_hpd_sts(void)
{
int tmp;
tmp = hdmirx_rd_top(TOP_HPD_PWR5V) & (1 << rx.port);
tmp >>= rx.port;
return tmp;
}
void esm_set_reset(bool reset)
{
if (log_level & HDCP_LOG)
rx_pr("esm set reset:%d\n", reset);
esm_reset_flag = reset;
}
void esm_set_stable(bool stable)
{
if (log_level & HDCP_LOG)
rx_pr("esm set stable:%d\n", stable);
video_stable_to_esm = stable;
}
void esm_recovery(void)
{
if (hdcp22_stop_auth_enable)
hdcp22_stop_auth = 1;
if (hdcp22_esm_reset2_enable)
hdcp22_esm_reset2 = 1;
}
bool is_unnormal_format(uint8_t wait_cnt)
{
bool ret = false;
if ((rx.pre.sw_vic == HDMI_UNSUPPORT) ||
(rx.pre.sw_vic == HDMI_UNKNOWN)) {
ret = true;
if (wait_cnt == sig_stable_max)
rx_pr("*unsupport*\n");
if (unnormal_wait_max == wait_cnt) {
dump_state(RX_DUMP_VIDEO);
ret = false;
}
}
if (rx.pre.sw_dvi == 1) {
ret = true;
if (wait_cnt == sig_stable_max)
rx_pr("*DVI*\n");
if (unnormal_wait_max == wait_cnt) {
dump_state(RX_DUMP_VIDEO);
ret = false;
}
}
if ((rx.pre.hdcp14_state != 3) &&
(rx.pre.hdcp14_state != 0) &&
(rx.hdcp.hdcp_version == HDCP_VER_14)) {
ret = true;
if (sig_stable_max == wait_cnt)
rx_pr("hdcp14 unfinished\n");
if (unnormal_wait_max == wait_cnt) {
if ((hdmirx_rd_dwc(DWC_HDCP_BKSV1) == 0) &&
(hdmirx_rd_dwc(DWC_HDCP_BKSV0) == 0))
rx.err_code = ERR_NO_HDCP14_KEY;
ret = false;
}
}
if (rx.hdcp.hdcp_version == HDCP_VER_NONE) {
ret = true;
if (wait_cnt == hdcp_none_wait_max) {
ret = false;
if (log_level & VIDEO_LOG)
rx_pr("hdcp none waiting\n");
}
}
if ((ret == false) && (wait_cnt != sig_stable_max))
if (log_level & VIDEO_LOG)
rx_pr("unnormal_format wait cnt = %d\n",
wait_cnt-sig_stable_max);
return ret;
}
void fsm_restart(void)
{
if (hdcp22_on) {
if (esm_recovery_mode == ESM_REC_MODE_TMDS)
rx_esm_tmdsclk_en(false);
esm_set_stable(false);
}
hdmirx_hw_config();
hdmi_rx_top_edid_update();
set_scdc_cfg(1, 0);
vic_check_en = true;
dvi_check_en = true;
rx.state = FSM_INIT;
rx.phy.cable_clk = 0;
rx.phy.pll_rate = 0;
rx.phy.phy_bw = 0;
rx.phy.pll_bw = 0;
rx_pr("force_fsm_init\n");
}
void dump_unnormal_info(void)
{
if (rx.pre.colorspace != rx.cur.colorspace)
rx_pr("colorspace:%d-%d\n",
rx.pre.colorspace,
rx.cur.colorspace);
if (rx.pre.colordepth != rx.cur.colordepth)
rx_pr("colordepth:%d-%d\n",
rx.pre.colordepth,
rx.cur.colordepth);
if (rx.pre.interlaced != rx.cur.interlaced)
rx_pr("interlace:%d-%d\n",
rx.pre.interlaced,
rx.cur.interlaced);
if (rx.pre.htotal != rx.cur.htotal)
rx_pr("htotal:%d-%d\n",
rx.pre.htotal,
rx.cur.htotal);
if (rx.pre.hactive != rx.cur.hactive)
rx_pr("hactive:%d-%d\n",
rx.pre.hactive,
rx.cur.hactive);
if (rx.pre.vtotal != rx.cur.vtotal)
rx_pr("vtotal:%d-%d\n",
rx.pre.vtotal,
rx.cur.vtotal);
if (rx.pre.vactive != rx.cur.vactive)
rx_pr("vactive:%d-%d\n",
rx.pre.vactive,
rx.cur.vactive);
if (rx.pre.repeat != rx.cur.repeat)
rx_pr("repetition:%d-%d\n",
rx.pre.repeat,
rx.cur.repeat);
if (rx.pre.frame_rate != rx.cur.frame_rate)
rx_pr("frame_rate:%d-%d\n",
rx.pre.frame_rate,
rx.cur.frame_rate);
if (rx.pre.hw_dvi != rx.cur.hw_dvi)
rx_pr("dvi:%d-%d\n,",
rx.pre.hw_dvi,
rx.cur.hw_dvi);
if (rx.pre.hdcp14_state != rx.cur.hdcp14_state)
rx_pr("HDCP14 state:%d-%d\n",
rx.pre.hdcp14_state,
rx.cur.hdcp14_state);
if (rx.pre.hdcp22_state != rx.cur.hdcp22_state)
rx_pr("HDCP22 state:%d-%d\n",
rx.pre.hdcp22_state,
rx.cur.hdcp22_state);
}
void rx_send_hpd_pulse(void)
{
/*rx_set_cur_hpd(0);*/
/*fsm_restart();*/
rx.state = FSM_HPD_LOW;
}
static void set_hdcp(struct hdmi_rx_hdcp *hdcp, const unsigned char *b_key)
{
int i, j;
/*memset(&init_hdcp_data, 0, sizeof(struct hdmi_rx_hdcp));*/
for (i = 0, j = 0; i < 80; i += 2, j += 7) {
hdcp->keys[i + 1] =
b_key[j] | (b_key[j + 1] << 8) | (b_key[j + 2] << 16) |
(b_key[j + 3] << 24);
hdcp->keys[i + 0] =
b_key[j + 4] | (b_key[j + 5] << 8) | (b_key[j + 6] << 16);
}
hdcp->bksv[1] =
b_key[j] | (b_key[j + 1] << 8) | (b_key[j + 2] << 16) |
(b_key[j + 3] << 24);
hdcp->bksv[0] = b_key[j + 4];
}
#if 0
int hdmirx_read_key_buf(char *buf, int max_size)
{
if (key_size > max_size) {
rx_pr("Error: %s,key size %d",
__func__, key_size);
rx_pr("is larger than the buf size of %d\n", max_size);
return 0;
}
memcpy(buf, key_buf, key_size);
rx_pr("HDMIRX: read key buf\n");
return key_size;
}
#endif
/*
* func: hdmirx_fill_key_buf
*/
void hdmirx_fill_key_buf(const char *buf, int size)
{
if (buf[0] == 'k' && buf[1] == 'e' && buf[2] == 'y') {
set_hdcp(&rx.hdcp, buf + 3);
} else {
//memcpy(key_buf, buf, size);
//key_size = size;
//rx_pr("HDMIRX: fill key buf, size %d\n", size);
}
hdcp14_on = 1;
rx_pr("HDMIRX: fill key buf, hdcp14_on %d\n", hdcp14_on);
}
/*
*debug functions
*/
unsigned int hdmirx_hw_dump_reg(unsigned char *buf, int size)
{
return 0;
}
bool comp_set_pr_var(unsigned char *buff, unsigned char *var_str,
void *var, int val, unsigned int *index, int ret, int size)
{
char index_c[5] = {'\0'};
sprintf(index_c, "%d", (*index));
if (str_cmp(buff, var_str) || str_cmp((buff), (index_c))) {
if (!ret)
memcpy(var, &val, size);
return true;
}
(*index)++;
return false;
}
int rx_set_global_variable(const char *buf, int size)
{
char tmpbuf[60];
int i = 0;
uint32_t value = 0;
int ret = 0;
int index = 1;
/* rx_pr("buf: %s size: %#x\n", buf, size); */
if ((buf == 0) || (size == 0) || (size > 60))
return -1;
memset(tmpbuf, 0, sizeof(tmpbuf));
while ((buf[i]) && (buf[i] != ',') && (buf[i] != ' ') &&
(buf[i] != '\n') && (i < size)) {
tmpbuf[i] = buf[i];
i++;
}
/*skip the space*/
while (++i < size) {
if ((buf[i] != ' ') && (buf[i] != ','))
break;
}
if ((buf[i] == '0') && ((buf[i + 1] == 'x') || (buf[i + 1] == 'X')))
ret = kstrtou32(buf + i + 2, 16, &value);
else
ret = kstrtou32(buf + i, 10, &value);
/*rx_pr("tmpbuf: %s value: %#x index:%#x\n", tmpbuf, value, index);*/
if (ret != 0)
rx_pr("No value set:%d\n", ret);
if (set_pr_var(tmpbuf, dwc_rst_wait_cnt_max, value, &index, ret))
return pr_var(dwc_rst_wait_cnt_max, index);
if (set_pr_var(tmpbuf, sig_stable_max, value, &index, ret))
return pr_var(sig_stable_max, index);
if (set_pr_var(tmpbuf, clk_debug, value, &index, ret))
return pr_var(clk_debug, index);
if (set_pr_var(tmpbuf, hpd_wait_max, value, &index, ret))
return pr_var(hpd_wait_max, index);
if (set_pr_var(tmpbuf, sig_unstable_max, value, &index, ret))
return pr_var(sig_unstable_max, index);
if (set_pr_var(tmpbuf, sig_unready_max, value, &index, ret))
return pr_var(sig_unready_max, index);
if (set_pr_var(tmpbuf, pow5v_max_cnt, value, &index, ret))
return pr_var(pow5v_max_cnt, index);
if (set_pr_var(tmpbuf, rgb_quant_range, value, &index, ret))
return pr_var(rgb_quant_range, index);
if (set_pr_var(tmpbuf, yuv_quant_range, value, &index, ret))
return pr_var(yuv_quant_range, index);
if (set_pr_var(tmpbuf, it_content, value, &index, ret))
return pr_var(it_content, index);
if (set_pr_var(tmpbuf, diff_pixel_th, value, &index, ret))
return pr_var(diff_pixel_th, index);
if (set_pr_var(tmpbuf, diff_line_th, value, &index, ret))
return pr_var(diff_line_th, index);
if (set_pr_var(tmpbuf, diff_frame_th, value, &index, ret))
return pr_var(diff_frame_th, index);
if (set_pr_var(tmpbuf, force_vic, value, &index, ret))
return pr_var(force_vic, index);
if (set_pr_var(tmpbuf, aud_sr_stb_max, value, &index, ret))
return pr_var(aud_sr_stb_max, index);
if (set_pr_var(tmpbuf, hdcp22_kill_esm, value, &index, ret))
return pr_var(hdcp22_kill_esm, index);
if (set_pr_var(tmpbuf, mute_kill_en, value, &index, ret))
return pr_var(mute_kill_en, index);
if (set_pr_var(tmpbuf, hdcp_mode_sel, value, &index, ret))
return pr_var(hdcp_mode_sel, index);
if (set_pr_var(tmpbuf, audio_sample_rate, value, &index, ret))
return pr_var(audio_sample_rate, index);
if (set_pr_var(tmpbuf, auds_rcv_sts, value, &index, ret))
return pr_var(auds_rcv_sts, index);
if (set_pr_var(tmpbuf, audio_coding_type, value, &index, ret))
return pr_var(audio_coding_type, index);
if (set_pr_var(tmpbuf, audio_channel_count, value, &index, ret))
return pr_var(audio_channel_count, index);
if (set_pr_var(tmpbuf, hdcp22_capable_sts, value, &index, ret))
return pr_var(hdcp22_capable_sts, index);
if (set_pr_var(tmpbuf, esm_auth_fail_en, value, &index, ret))
return pr_var(esm_auth_fail_en, index);
if (set_pr_var(tmpbuf, hdcp22_auth_sts, value, &index, ret))
return pr_var(hdcp22_auth_sts, index);
if (set_pr_var(tmpbuf, log_level, value, &index, ret))
return pr_var(log_level, index);
if (set_pr_var(tmpbuf, auto_switch_off, value, &index, ret))
return pr_var(auto_switch_off, index);
if (set_pr_var(tmpbuf, clk_unstable_cnt, value, &index, ret))
return pr_var(clk_unstable_cnt, index);
if (set_pr_var(tmpbuf, clk_unstable_max, value, &index, ret))
return pr_var(clk_unstable_max, index);
if (set_pr_var(tmpbuf, clk_stable_cnt, value, &index, ret))
return pr_var(clk_stable_cnt, index);
if (set_pr_var(tmpbuf, clk_stable_max, value, &index, ret))
return pr_var(clk_stable_max, index);
if (set_pr_var(tmpbuf, wait_no_sig_max, value, &index, ret))
return pr_var(wait_no_sig_max, index);
if (set_pr_var(tmpbuf, receive_edid_len, value, &index, ret))
return pr_var(receive_edid_len, index);
if (set_pr_var(tmpbuf, new_edid, value, &index, ret))
return pr_var(new_edid, index);
if (set_pr_var(tmpbuf, hdcp_array_len, value, &index, ret))
return pr_var(hdcp_array_len, index);
if (set_pr_var(tmpbuf, hdcp_len, value, &index, ret))
return pr_var(hdcp_len, index);
if (set_pr_var(tmpbuf, hdcp_repeat_depth, value, &index, ret))
return pr_var(hdcp_repeat_depth, index);
if (set_pr_var(tmpbuf, new_hdcp, value, &index, ret))
return pr_var(new_hdcp, index);
if (set_pr_var(tmpbuf, repeat_plug, value, &index, ret))
return pr_var(repeat_plug, index);
if (set_pr_var(tmpbuf, up_phy_addr, value, &index, ret))
return pr_var(up_phy_addr, index);
if (set_pr_var(tmpbuf, hpd_to_esm, value, &index, ret))
return pr_var(hpd_to_esm, index);
if (set_pr_var(tmpbuf, esm_reset_flag, value, &index, ret))
return pr_var(esm_reset_flag, index);
if (set_pr_var(tmpbuf, video_stable_to_esm, value, &index, ret))
return pr_var(video_stable_to_esm, index);
if (set_pr_var(tmpbuf, enable_hdcp22_esm_log, value, &index, ret))
return pr_var(enable_hdcp22_esm_log, index);
if (set_pr_var(tmpbuf, esm_error_flag, value, &index, ret))
return pr_var(esm_error_flag, index);
if (set_pr_var(tmpbuf, stable_check_lvl, value, &index, ret))
return pr_var(stable_check_lvl, index);
if (set_pr_var(tmpbuf, hdcp22_reauth_enable, value, &index, ret))
return pr_var(hdcp22_reauth_enable, index);
if (set_pr_var(tmpbuf, hdcp22_stop_auth_enable, value, &index, ret))
return pr_var(hdcp22_stop_auth_enable, index);
if (set_pr_var(tmpbuf, hdcp22_stop_auth, value, &index, ret))
return pr_var(hdcp22_stop_auth, index);
if (set_pr_var(tmpbuf, hdcp22_esm_reset2_enable, value, &index, ret))
return pr_var(hdcp22_esm_reset2_enable, index);
if (set_pr_var(tmpbuf, hdcp22_esm_reset2, value, &index, ret))
return pr_var(hdcp22_esm_reset2, index);
if (set_pr_var(tmpbuf, esm_recovery_mode, value, &index, ret))
return pr_var(esm_recovery_mode, index);
if (set_pr_var(tmpbuf, unnormal_wait_max, value, &index, ret))
return pr_var(unnormal_wait_max, index);
if (set_pr_var(tmpbuf, edid_update_delay, value, &index, ret))
return pr_var(edid_update_delay, index);
if (set_pr_var(tmpbuf, hdmi_yuv444_enable, value, &index, ret))
return pr_var(hdmi_yuv444_enable, index);
if (set_pr_var(tmpbuf, pc_mode_en, value, &index, ret))
return pr_var(pc_mode_en, index);
if (set_pr_var(tmpbuf, en_4k_2_2k, value, &index, ret))
return pr_var(en_4k_2_2k, index);
if (set_pr_var(tmpbuf, en_4096_2_3840, value, &index, ret))
return pr_var(en_4096_2_3840, index);
if (set_pr_var(tmpbuf, en_4k_timing, value, &index, ret))
return pr_var(en_4k_timing, index);
if (set_pr_var(tmpbuf, acr_mode, value, &index, ret))
return pr_var(acr_mode, index);
if (set_pr_var(tmpbuf, force_clk_rate, value, &index, ret))
return pr_var(force_clk_rate, index);
if (set_pr_var(tmpbuf, auto_aclk_mute, value, &index, ret))
return pr_var(auto_aclk_mute, index);
if (set_pr_var(tmpbuf, aud_avmute_en, value, &index, ret))
return pr_var(aud_avmute_en, index);
if (set_pr_var(tmpbuf, aud_mute_sel, value, &index, ret))
return pr_var(aud_mute_sel, index);
if (set_pr_var(tmpbuf, md_ists_en, value, &index, ret))
return pr_var(md_ists_en, index);
if (set_pr_var(tmpbuf, pdec_ists_en, value, &index, ret))
return pr_var(pdec_ists_en, index);
if (set_pr_var(tmpbuf, packet_fifo_cfg, value, &index, ret))
return pr_var(packet_fifo_cfg, index);
if (set_pr_var(tmpbuf, pd_fifo_start_cnt, value, &index, ret))
return pr_var(pd_fifo_start_cnt, index);
if (set_pr_var(tmpbuf, hdcp22_on, value, &index, ret))
return pr_var(hdcp22_on, index);
if (set_pr_var(tmpbuf, dv_nopacket_timeout, value, &index, ret))
return pr_var(dv_nopacket_timeout, index);
if (set_pr_var(tmpbuf, delay_ms_cnt, value, &index, ret))
return pr_var(delay_ms_cnt, index);
if (set_pr_var(tmpbuf, downstream_repeat_support, value, &index, ret))
return pr_var(downstream_repeat_support, index);
if (set_pr_var(tmpbuf, eq_max_setting, value, &index, ret))
return pr_var(eq_max_setting, index);
if (set_pr_var(tmpbuf, eq_dbg_ch0, value, &index, ret))
return pr_var(eq_dbg_ch0, index);
if (set_pr_var(tmpbuf, eq_dbg_ch1, value, &index, ret))
return pr_var(eq_dbg_ch1, index);
if (set_pr_var(tmpbuf, eq_dbg_ch2, value, &index, ret))
return pr_var(eq_dbg_ch2, index);
if (set_pr_var(tmpbuf, edid_mode, value, &index, ret))
return pr_var(edid_mode, index);
if (set_pr_var(tmpbuf, phy_pddq_en, value, &index, ret))
return pr_var(edid_mode, index);
if (set_pr_var(tmpbuf, long_cable_best_setting, value, &index, ret))
return pr_var(long_cable_best_setting, index);
if (set_pr_var(tmpbuf, port_map, value, &index, ret))
return pr_var(port_map, index);
if (set_pr_var(tmpbuf, new_hdr_lum, value, &index, ret))
return pr_var(new_hdr_lum, index);
if (set_pr_var(tmpbuf, skip_frame_cnt, value, &index, ret))
return pr_var(skip_frame_cnt, index);
if (set_pr_var(tmpbuf, vdin_drop_frame_cnt, value, &index, ret))
return pr_var(vdin_drop_frame_cnt, index);
if (set_pr_var(tmpbuf, atmos_edid_update_hpd_en, value, &index, ret))
return pr_var(atmos_edid_update_hpd_en, index);
if (set_pr_var(tmpbuf, suspend_pddq_sel, value, &index, ret))
return pr_var(suspend_pddq_sel, index);
if (set_pr_var(tmpbuf, aud_ch_map, value, &index, ret))
return pr_var(aud_ch_map, index);
if (set_pr_var(tmpbuf, hdcp_none_wait_max, value, &index, ret))
return pr_var(hdcp_none_wait_max, index);
if (set_pr_var(tmpbuf, pll_unlock_max, value, &index, ret))
return pr_var(pll_unlock_max, index);
if (set_pr_var(tmpbuf, esd_phy_rst_max, value, &index, ret))
return pr_var(esd_phy_rst_max, index);
if (set_pr_var(tmpbuf, ignore_sscp_charerr, value, &index, ret))
return pr_var(ignore_sscp_charerr, index);
if (set_pr_var(tmpbuf, ignore_sscp_tmds, value, &index, ret))
return pr_var(ignore_sscp_tmds, index);
if (set_pr_var(tmpbuf, fsm_log_en, value, &index, ret))
return pr_var(fsm_log_en, index);
if (set_pr_var(tmpbuf, err_chk_en, value, &index, ret))
return pr_var(err_chk_en, index);
if (set_pr_var(tmpbuf, phy_retry_times, value, &index, ret))
return pr_var(phy_retry_times, index);
if (set_pr_var(tmpbuf, find_best_eq, value, &index, ret))
return pr_var(find_best_eq, index);
if (set_pr_var(tmpbuf, eq_try_cnt, value, &index, ret))
return pr_var(eq_try_cnt, index);
if (set_pr_var(tmpbuf, pll_rst_max, value, &index, ret))
return pr_var(pll_rst_max, index);
if (set_pr_var(tmpbuf, hdcp_enc_mode, value, &index, ret))
return pr_var(hdcp_enc_mode, index);
if (set_pr_var(tmpbuf, hbr_force_8ch, value, &index, ret))
return pr_var(hbr_force_8ch, index);
return 0;
}
void rx_get_global_variable(const char *buf)
{
int i = 1;
rx_pr("index %-30s value\n", "varaible");
pr_var(dwc_rst_wait_cnt_max, i++);
pr_var(sig_stable_max, i++);
pr_var(clk_debug, i++);
pr_var(hpd_wait_max, i++);
pr_var(sig_unstable_max, i++);
pr_var(sig_unready_max, i++);
pr_var(pow5v_max_cnt, i++);
pr_var(rgb_quant_range, i++);
pr_var(yuv_quant_range, i++);
pr_var(it_content, i++);
pr_var(diff_pixel_th, i++);
pr_var(diff_line_th, i++);
pr_var(diff_frame_th, i++);
pr_var(force_vic, i++);
pr_var(aud_sr_stb_max, i++);
pr_var(hdcp22_kill_esm, i++);
pr_var(mute_kill_en, i++);
pr_var(hdcp_mode_sel, i++);
pr_var(audio_sample_rate, i++);
pr_var(auds_rcv_sts, i++);
pr_var(audio_coding_type, i++);
pr_var(audio_channel_count, i++);
pr_var(hdcp22_capable_sts, i++);
pr_var(esm_auth_fail_en, i++);
pr_var(hdcp22_auth_sts, i++);
pr_var(log_level, i++);
pr_var(auto_switch_off, i++);
pr_var(clk_unstable_cnt, i++);
pr_var(clk_unstable_max, i++);
pr_var(clk_stable_cnt, i++);
pr_var(clk_stable_max, i++);
pr_var(wait_no_sig_max, i++);
pr_var(receive_edid_len, i++);
pr_var(new_edid, i++);
pr_var(hdcp_array_len, i++);
pr_var(hdcp_len, i++);
pr_var(hdcp_repeat_depth, i++);
pr_var(new_hdcp, i++);
pr_var(repeat_plug, i++);
pr_var(up_phy_addr, i++);
pr_var(hpd_to_esm, i++);
pr_var(esm_reset_flag, i++);
pr_var(video_stable_to_esm, i++);
pr_var(enable_hdcp22_esm_log, i++);
pr_var(esm_error_flag, i++);
pr_var(stable_check_lvl, i++);
pr_var(hdcp22_reauth_enable, i++);
pr_var(hdcp22_stop_auth_enable, i++);
pr_var(hdcp22_stop_auth, i++);
pr_var(hdcp22_esm_reset2_enable, i++);
pr_var(hdcp22_esm_reset2, i++);
pr_var(esm_recovery_mode, i++);
pr_var(unnormal_wait_max, i++);
pr_var(edid_update_delay, i++);
pr_var(hdmi_yuv444_enable, i++);
pr_var(pc_mode_en, i++);
pr_var(en_4k_2_2k, i++);
pr_var(en_4096_2_3840, i++);
pr_var(en_4k_timing, i++);
pr_var(acr_mode, i++);
pr_var(force_clk_rate, i++);
pr_var(auto_aclk_mute, i++);
pr_var(aud_avmute_en, i++);
pr_var(aud_mute_sel, i++);
pr_var(md_ists_en, i++);
pr_var(pdec_ists_en, i++);
pr_var(packet_fifo_cfg, i++);
pr_var(pd_fifo_start_cnt, i++);
pr_var(hdcp22_on, i++);
pr_var(dv_nopacket_timeout, i++);
pr_var(delay_ms_cnt, i++);
pr_var(downstream_repeat_support, i++);
pr_var(eq_max_setting, i++);
pr_var(eq_dbg_ch0, i++);
pr_var(eq_dbg_ch1, i++);
pr_var(eq_dbg_ch2, i++);
pr_var(edid_mode, i++);
pr_var(phy_pddq_en, i++);
pr_var(long_cable_best_setting, i++);
pr_var(port_map, i++);
pr_var(new_hdr_lum, i++);
pr_var(skip_frame_cnt, i++);
pr_var(vdin_drop_frame_cnt, i++);
pr_var(atmos_edid_update_hpd_en, i++);
pr_var(suspend_pddq_sel, i++);
pr_var(aud_ch_map, i++);
pr_var(hdcp_none_wait_max, i++);
pr_var(pll_unlock_max, i++);
pr_var(esd_phy_rst_max, i++);
pr_var(ignore_sscp_charerr, i++);
pr_var(ignore_sscp_tmds, i++);
pr_var(fsm_log_en, i++);
pr_var(err_chk_en, i++);
pr_var(phy_retry_times, i++);
pr_var(find_best_eq, i++);
pr_var(eq_try_cnt, i++);
pr_var(pll_rst_max, i++);
pr_var(hdcp_enc_mode, i++);
pr_var(hbr_force_8ch, i++);
}
void skip_frame(unsigned int cnt)
{
if (rx.state == FSM_SIG_READY) {
rx.skip = (1000 * 100 / rx.pre.frame_rate / 10) + 1;
rx.skip = cnt * rx.skip;
}
rx_pr("rx.skip = %d\n", rx.skip);
}
void wait_ddc_idle(void)
{
unsigned char i;
/* add delays to avoid the edid communication fail */
for (i = 0; i <= 10; i++) {
if (!is_ddc_idle(rx.port))
msleep(20);
}
}
/***********************
* hdmirx_open_port
***********************/
void hdmirx_open_port(enum tvin_port_e port)
{
uint32_t fsmst = sm_pause;
/* stop fsm when swich port */
sm_pause = 1;
rx.port = (port - TVIN_PORT_HDMI0) & 0xf;
//rx.no_signal = false;
//rx.wait_no_sig_cnt = 0;
vic_check_en = true;
dvi_check_en = true;
if (hdmirx_repeat_support())
rx.hdcp.repeat = repeat_plug;
else
rx.hdcp.repeat = 0;
if ((pre_port != rx.port) ||
(rx_get_cur_hpd_sts() == 0) ||
/* when open specific port, force to enable it */
(disable_port_en && (rx.port == disable_port_num))) {
if (hdcp22_on) {
esm_set_stable(false);
esm_set_reset(true);
if (esm_recovery_mode == ESM_REC_MODE_TMDS)
rx_esm_tmdsclk_en(false);
/*hpd_to_esm = 1;*/
/* switch_set_state(&rx.hpd_sdev, 0x01); */
if (log_level & VIDEO_LOG)
rx_pr("switch_set_state:%d\n", pwr_sts);
}
if (rx.state > FSM_HPD_LOW)
rx.state = FSM_HPD_LOW;
rx_set_cur_hpd(0);
/* need reset the whole module when switch port */
hdmirx_hw_config();
wait_ddc_idle();
hdmi_rx_top_edid_update();
} else {
if (rx.state >= FSM_SIG_STABLE)
rx.state = FSM_SIG_STABLE;
else if (rx.state >= FSM_HPD_HIGH)
rx.state = FSM_HPD_HIGH;
}
edid_update_flag = 0;
rx_pkt_initial();
sm_pause = fsmst;
extcon_set_state_sync(rx.rx_excton_open, EXTCON_DISP_HDMI, 1);
rx_pr("%s:%d\n", __func__, rx.port);
}
void hdmirx_close_port(void)
{
/* if (sm_pause) */
/* return; */
/* External_Mute(1); */
/* when exit hdmi, disable termination & hpd of specific port */
if (disable_port_en)
rx_set_port_hpd(disable_port_num, 0);
extcon_set_state_sync(rx.rx_excton_open, EXTCON_DISP_HDMI, 0);
}
void rx_nosig_monitor(void)
{
if (rx.cur_5v_sts == 0)
rx.no_signal = true;
else if (rx.state != FSM_SIG_READY) {
if (rx.wait_no_sig_cnt >= wait_no_sig_max)
rx.no_signal = true;
else {
rx.wait_no_sig_cnt++;
if (rx.no_signal)
rx.no_signal = false;
}
} else {
rx.wait_no_sig_cnt = 0;
rx.no_signal = false;
}
}
static void rx_cable_clk_monitor(void)
{
static bool pre_sts;
bool sts = is_clk_stable();
if (pre_sts != sts) {
rx_pr("\nclk stable = %d\n", sts);
pre_sts = sts;
}
}
/* ---------------------------------------------------------- */
/* func: port A,B,C,D hdmitx-5v monitor & HPD control */
/* note: G9TV portD no used */
/* ---------------------------------------------------------- */
void rx_5v_monitor(void)
{
static uint8_t check_cnt;
uint8_t tmp_5v = rx_get_hdmi5v_sts();
if (auto_switch_off)
tmp_5v = 0x0f;
if (tmp_5v != pwr_sts)
check_cnt++;
if (check_cnt >= pow5v_max_cnt) {
check_cnt = 0;
pwr_sts = tmp_5v;
rx.cur_5v_sts = (pwr_sts >> rx.port) & 1;
hotplug_wait_query();
if (rx.cur_5v_sts == 0) {
set_fsm_state(FSM_5V_LOST);
rx.err_code = ERR_5V_LOST;
vic_check_en = true;
dvi_check_en = true;
}
}
rx.cur_5v_sts = (pwr_sts >> rx.port) & 1;
/* inform hdcp_rx22 the 5v sts of rx */
if (hdcp22_on) {
if (!pwr_sts)
hdcp_mode_sel = true;
else
hdcp_mode_sel = false;
}
}
/*
* function:
* for check error counter start for tl1
*
*/
void rx_monitor_error_cnt_start(void)
{
rx.phy.timestap = get_seconds();
}
/*
* function:
* 1min error counter check for tl1 aml phy
*/
void rx_monitor_error_counter(void)
{
ulong timestap;
uint32_t ch0, ch1, ch2;
if (rx.chip_id != CHIP_ID_TL1)
return;
timestap = get_seconds();
if ((timestap - rx.phy.timestap) > 1) {
rx.phy.timestap = timestap;
rx_get_error_cnt(&ch0, &ch1, &ch2);
if (ch0 || ch1 || ch2)
rx_pr("err cnt:%d,%d,%d\n", ch0, ch1, ch2);
}
}
void rx_err_monitor(void)
{
//static bool hdcp14_sts;
if (clk_debug)
rx_cable_clk_monitor();
rx.timestamp++;
if (rx.err_code == ERR_NONE)
return;
if (err_dbg_cnt++ > err_dbg_cnt_max)
//return;
err_dbg_cnt = 0;
//rx_pr("err_code = %d\n", rx.err_code);
switch (rx.err_code) {
case ERR_5V_LOST:
if (err_dbg_cnt == 0)
rx_pr("hdmi-5v-state = %x\n", pwr_sts);
break;
case ERR_CLK_UNSTABLE:
if (err_dbg_cnt == 0)
rx_pr("clk unstable = %d\n",
is_clk_stable());
break;
case ERR_PHY_UNLOCK:
if (err_dbg_cnt == 0) {
if (rx.chip_id != CHIP_ID_TL1)
rx_pr("EQ = %d-%d-%d\n",
eq_ch0.bestsetting,
eq_ch1.bestsetting,
eq_ch2.bestsetting);
else
rx_pr("PHY unlock\n");
}
break;
case ERR_DE_UNSTABLE:
if (err_dbg_cnt == 0)
dump_unnormal_info();
break;
case ERR_NO_HDCP14_KEY:
if (err_dbg_cnt == 0) {
rx_pr("NO HDCP1.4 KEY\n");
rx_pr("bksv = %d,%d", rx.hdcp.bksv[0], rx.hdcp.bksv[1]);
}
break;
case ERR_TIMECHANGE:
//rx_pr("ready time = %d", rx.unready_timestamp);
//rx_pr("stable time = %d", rx.stable_timestamp);
if (((rx.unready_timestamp - rx.stable_timestamp) < 30) &&
(rx_get_eq_run_state() == E_EQ_SAME)) {
rx.err_cnt++;
rx_pr("timingchange warning cnt = %d\n", rx.err_cnt);
}
if (rx.err_cnt > 3) {
fsm_restart();
rx.err_cnt = 0;
}
rx.err_code = ERR_NONE;
break;
default:
break;
}
}
char *fsm_st[] = {
"FSM_5V_LOST",
"FSM_INIT",
"FSM_HPD_LOW",
"FSM_HPD_HIGH",
"FSM_WAIT_CLK_STABLE",
"FSM_EQ_START",
"FSM_WAIT_EQ_DONE",
"FSM_SIG_UNSTABLE",
"FSM_SIG_WAIT_STABLE",
"FSM_SIG_STABLE",
"FSM_SIG_READY",
"FSM_NULL",
};
/*
* FUNC: rx_main_state_machine
* signal detection main process
*/
void rx_main_state_machine(void)
{
int pre_auds_ch_alloc;
int pre_auds_hbr;
switch (rx.state) {
case FSM_5V_LOST:
if (rx.cur_5v_sts)
rx.state = FSM_INIT;
fsm_restart();
break;
case FSM_HPD_LOW:
rx_set_cur_hpd(0);
set_scdc_cfg(1, 0);
rx.state = FSM_INIT;
break;
case FSM_INIT:
signal_status_init();
rx.phy.cable_clk = 0;
rx.state = FSM_HPD_HIGH;
break;
case FSM_HPD_HIGH:
hpd_wait_cnt++;
if ((rx_get_cur_hpd_sts() == 0) &&
rx_hpd_keep_low()) {
break;
}
hpd_wait_cnt = 0;
clk_unstable_cnt = 0;
esd_phy_rst_cnt = 0;
downstream_hpd_flag = 0;
pre_port = rx.port;
rx_set_cur_hpd(1);
rx.phy.cable_clk = 0;
rx.phy.cablesel = 0;
set_scdc_cfg(0, 1);
/* rx.hdcp.hdcp_version = HDCP_VER_NONE; */
rx.state = FSM_WAIT_CLK_STABLE;
break;
case FSM_WAIT_CLK_STABLE:
if (is_clk_stable()) {
if (clk_unstable_cnt != 0) {
rx_pr("wait clk cnt %d\n", clk_unstable_cnt);
clk_unstable_cnt = 0;
}
if (++clk_stable_cnt > clk_stable_max) {
rx.state = FSM_EQ_START;
clk_stable_cnt = 0;
rx.err_code = ERR_NONE;
}
} else {
clk_stable_cnt = 0;
if (clk_unstable_cnt < clk_unstable_max) {
clk_unstable_cnt++;
break;
}
clk_unstable_cnt = 0;
if (esd_phy_rst_cnt < esd_phy_rst_max) {
hdmirx_phy_init();
rx.phy.cable_clk = 0;
esd_phy_rst_cnt++;
}
rx.err_code = ERR_CLK_UNSTABLE;
}
break;
case FSM_EQ_START:
rx_run_eq();
rx.state = FSM_WAIT_EQ_DONE;
break;
case FSM_WAIT_EQ_DONE:
if (rx_eq_done()) {
rx.state = FSM_SIG_UNSTABLE;
pll_lock_cnt = 0;
pll_unlock_cnt = 0;
}
break;
case FSM_SIG_UNSTABLE:
if (is_tmds_valid()) {
pll_unlock_cnt = 0;
if (++pll_lock_cnt < pll_lock_max)
break;
rx_dwc_reset();
rx.err_code = ERR_NONE;
rx.state = FSM_SIG_WAIT_STABLE;
} else {
pll_lock_cnt = 0;
if (pll_unlock_cnt < pll_unlock_max) {
pll_unlock_cnt++;
break;
}
if (rx.err_rec_mode == ERR_REC_EQ_RETRY) {
rx.state = FSM_WAIT_CLK_STABLE;
if (esd_phy_rst_cnt++ < esd_phy_rst_max) {
rx.phy.cablesel++;
rx_pr("cablesel=%d\n", rx.phy.cablesel);
rx.phy.cable_clk = 0;
/* hdmirx_phy_init(); */
} else
rx.err_rec_mode = ERR_REC_HPD_RST;
} else if (rx.err_rec_mode == ERR_REC_HPD_RST) {
rx_set_cur_hpd(0);
rx.phy.cable_clk = 0;
rx.state = FSM_HPD_HIGH;
rx.err_rec_mode = ERR_REC_EQ_RETRY;
}
rx_set_eq_run_state(E_EQ_START);
}
break;
case FSM_SIG_WAIT_STABLE:
dwc_rst_wait_cnt++;
if (dwc_rst_wait_cnt < dwc_rst_wait_cnt_max)
break;
if ((edid_update_flag) &&
(dwc_rst_wait_cnt < edid_update_delay))
break;
edid_update_flag = 0;
dwc_rst_wait_cnt = 0;
sig_stable_cnt = 0;
sig_unstable_cnt = 0;
sig_stable_err_cnt = 0;
rx.state = FSM_SIG_STABLE;
break;
case FSM_SIG_STABLE:
memcpy(&rx.pre, &rx.cur,
sizeof(struct rx_video_info));
rx_get_video_info();
if (rx_is_timing_stable()) {
if (++sig_stable_cnt >= sig_stable_max) {
get_timing_fmt();
if (is_unnormal_format(sig_stable_cnt))
break;
/* if format vic is abnormal, do hw
* reset once to try to recover.
*/
if (fmt_vic_abnormal() &&
(vic_check_en == true)) {
hdmirx_hw_config();
hdmi_rx_top_edid_update();
rx.state = FSM_HPD_LOW;
//vic_check_en = false;
break;
}
sig_unready_cnt = 0;
/* if DVI signal is detected, then try
* hpd reset once to recovery, to avoid
* recognition to DVI of low probability
*/
if (rx.pre.sw_dvi && dvi_check_en &&
(rx.hdcp.hdcp_version ==
HDCP_VER_NONE)) {
rx.state = FSM_HPD_LOW;
dvi_check_en = false;
break;
}
rx.skip = 0;
rx.state = FSM_SIG_READY;
rx.aud_sr_stable_cnt = 0;
rx.aud_sr_unstable_cnt = 0;
rx.no_signal = false;
//memset(&rx.aud_info, 0,
//sizeof(struct aud_info_s));
//rx_set_eq_run_state(E_EQ_PASS);
hdmirx_config_video();
rx_get_audinfo(&rx.aud_info);
hdmirx_config_audio();
rx_aud_pll_ctl(1);
rx_afifo_store_all_subpkt(false);
hdmirx_audio_fifo_rst();
rx.stable_timestamp = rx.timestamp;
rx_pr("Sig ready\n");
dump_state(RX_DUMP_VIDEO);
#ifdef K_TEST_CHK_ERR_CNT
rx_monitor_error_cnt_start();
#endif
sig_stable_err_cnt = 0;
}
} else {
sig_stable_cnt = 0;
if (sig_unstable_cnt < sig_unstable_max) {
sig_unstable_cnt++;
break;
}
if (rx.err_rec_mode == ERR_REC_EQ_RETRY) {
rx.state = FSM_WAIT_CLK_STABLE;
rx.phy.cablesel++;
rx_pr("cablesel1=%d\n", rx.phy.cablesel);
rx.err_rec_mode = ERR_REC_HPD_RST;
rx_set_eq_run_state(E_EQ_START);
} else if (rx.err_rec_mode == ERR_REC_HPD_RST) {
rx_set_cur_hpd(0);
rx.phy.cable_clk = 0;
rx.state = FSM_HPD_HIGH;
rx.err_rec_mode = ERR_REC_EQ_RETRY;
}
}
break;
case FSM_SIG_READY:
rx_get_video_info();
rx.err_rec_mode = ERR_REC_EQ_RETRY;
#ifdef K_TEST_CHK_ERR_CNT
rx_monitor_error_counter();
#endif
/* video info change */
if ((!is_tmds_valid()) ||
(!rx_is_timing_stable())) {
skip_frame(skip_frame_cnt);
if (++sig_unready_cnt >= sig_unready_max) {
/*sig_lost_lock_cnt = 0;*/
rx.unready_timestamp = rx.timestamp;
rx.err_code = ERR_TIMECHANGE;
dump_unnormal_info();
rx_pr("sig ready exit: ");
rx_pr("tmdsvalid:%d, unready:%d\n",
hdmirx_rd_dwc(DWC_HDMI_PLL_LCK_STS),
sig_unready_cnt);
sig_unready_cnt = 0;
audio_sample_rate = 0;
rx_aud_pll_ctl(0);
rx.hdcp.hdcp_version = HDCP_VER_NONE;
rx.state = FSM_WAIT_CLK_STABLE;
/* rx.pre_state = FSM_SIG_READY; */
vic_check_en = true;
rx.skip = 0;
rx.aud_sr_stable_cnt = 0;
rx.aud_sr_unstable_cnt = 0;
rx.phy.cable_clk = 0;
esd_phy_rst_cnt = 0;
if (hdcp22_on) {
esm_set_stable(false);
if (esm_recovery_mode
== ESM_REC_MODE_RESET)
esm_set_reset(true);
/* for some hdcp2.2 devices which
* don't retry 2.2 interaction
* continuously and don't response
* to re-auth, such as chroma 2403,
* esm needs to be on work even
* before tmds is valid so that to
* not miss 2.2 interaction
*/
/* else */
/* rx_esm_tmdsclk_en(false); */
}
break;
}
} else {
sig_unready_cnt = 0;
if (rx.skip > 0)
rx.skip--;
}
if (rx.pre.sw_dvi == 1)
break;
packet_update();
pre_auds_ch_alloc = rx.aud_info.auds_ch_alloc;
pre_auds_hbr = rx.aud_info.aud_hbr_rcv;
rx_get_audinfo(&rx.aud_info);
if (check_real_sr_change())
rx_audio_pll_sw_update();
if ((pre_auds_ch_alloc != rx.aud_info.auds_ch_alloc) ||
((pre_auds_hbr != rx.aud_info.aud_hbr_rcv) &&
hbr_force_8ch)) {
if (log_level & AUDIO_LOG)
dump_state(RX_DUMP_AUDIO);
hdmirx_config_audio();
hdmirx_audio_fifo_rst();
rx_audio_pll_sw_update();
}
if (is_aud_pll_error()) {
rx.aud_sr_unstable_cnt++;
if (rx.aud_sr_unstable_cnt > aud_sr_stb_max) {
unsigned int aud_sts = rx_get_aud_pll_err_sts();
if (aud_sts == E_REQUESTCLK_ERR) {
hdmirx_phy_init();
rx.state = FSM_WAIT_CLK_STABLE;
/*timing sw at same FRQ*/
rx.phy.cable_clk = 0;
/*rx.pre_state = FSM_SIG_READY;*/
rx_pr("reqclk err->wait_clk\n");
} else if (aud_sts == E_PLLRATE_CHG)
rx_aud_pll_ctl(1);
else if (aud_sts == E_AUDCLK_ERR) {
rx_audio_bandgap_rst();
rx.aud_sr_stable_cnt = 0;
} else {
rx_acr_info_sw_update();
rx_audio_pll_sw_update();
if (log_level & AUDIO_LOG)
rx_pr("update audio-err\n");
}
rx.aud_sr_unstable_cnt = 0;
}
} else
rx.aud_sr_unstable_cnt = 0;
break;
default:
break;
}
/* for fsm debug */
if (fsm_log_en && (rx.state != rx.pre_state)) {
rx_pr("fsm state:%d(%s) to %d(%s)\n", rx.pre_state,
fsm_st[rx.pre_state], rx.state, fsm_st[rx.state]);
rx.pre_state = rx.state;
}
}
unsigned int hdmirx_show_info(unsigned char *buf, int size)
{
int pos = 0;
struct drm_infoframe_st *drmpkt;
drmpkt = (struct drm_infoframe_st *)&(rx_pkt.drm_info);
pos += snprintf(buf+pos, size-pos,
"HDMI info\n\n");
if (rx.cur.colorspace == E_COLOR_RGB)
pos += snprintf(buf+pos, size-pos,
"Color Space: %s\n", "0-RGB");
else if (rx.cur.colorspace == E_COLOR_YUV422)
pos += snprintf(buf+pos, size-pos,
"Color Space: %s\n", "1-YUV422");
else if (rx.cur.colorspace == E_COLOR_YUV444)
pos += snprintf(buf+pos, size-pos,
"Color Space: %s\n", "2-YUV444");
else if (rx.cur.colorspace == E_COLOR_YUV420)
pos += snprintf(buf+pos, size-pos,
"Color Space: %s\n", "3-YUV420");
pos += snprintf(buf+pos, size-pos,
"Dvi: %d\n", rx.cur.hw_dvi);
pos += snprintf(buf+pos, size-pos,
"Interlace: %d\n", rx.cur.interlaced);
pos += snprintf(buf+pos, size-pos,
"Htotal: %d\n", rx.cur.htotal);
pos += snprintf(buf+pos, size-pos,
"Hactive: %d\n", rx.cur.hactive);
pos += snprintf(buf+pos, size-pos,
"Vtotal: %d\n", rx.cur.vtotal);
pos += snprintf(buf+pos, size-pos,
"Vactive: %d\n", rx.cur.vactive);
pos += snprintf(buf+pos, size-pos,
"Repetition: %d\n", rx.cur.repeat);
pos += snprintf(buf+pos, size-pos,
"Color Depth: %d\n", rx.cur.colordepth);
pos += snprintf(buf+pos, size-pos,
"Frame Rate: %d\n", rx.cur.frame_rate);
pos += snprintf(buf+pos, size-pos,
"Skip frame: %d\n", rx.skip);
pos += snprintf(buf+pos, size-pos,
"avmute skip: %d\n", rx.avmute_skip);
pos += snprintf(buf+pos, size-pos,
"TMDS clock: %d\n", rx_measure_clock(MEASURE_CLK_TMDS));
pos += snprintf(buf+pos, size-pos,
"Pixel clock: %d\n", rx_measure_clock(MEASURE_CLK_PIXEL));
if (drmpkt->des_u.tp1.eotf == EOTF_SDR)
pos += snprintf(buf+pos, size-pos,
"HDR EOTF: %s\n", "SDR");
else if (drmpkt->des_u.tp1.eotf == EOTF_HDR)
pos += snprintf(buf+pos, size-pos,
"HDR EOTF: %s\n", "HDR");
else if (drmpkt->des_u.tp1.eotf == EOTF_SMPTE_ST_2048)
pos += snprintf(buf+pos, size-pos,
"HDR EOTF: %s\n", "SMPTE_ST_2048");
else if (drmpkt->des_u.tp1.eotf == EOTF_HLG)
pos += snprintf(buf+pos, size-pos,
"HDR EOTF: %s\n", "HLG");
pos += snprintf(buf+pos, size-pos,
"Dolby Vision: %s\n",
(rx.vs_info_details.dolby_vision?"on":"off"));
pos += snprintf(buf+pos, size-pos,
"\n\nAudio info\n\n");
pos += snprintf(buf+pos, size-pos,
"CTS: %d\n", rx.aud_info.cts);
pos += snprintf(buf+pos, size-pos,
"N: %d\n", rx.aud_info.n);
pos += snprintf(buf+pos, size-pos,
"Recovery clock: %d\n", rx.aud_info.arc);
pos += snprintf(buf+pos, size-pos,
"audio receive data: %d\n", auds_rcv_sts);
pos += snprintf(buf+pos, size-pos,
"Audio PLL clock: %d\n", rx_measure_clock(MEASURE_CLK_AUD_PLL));
pos += snprintf(buf+pos, size-pos,
"mpll_div_clk: %d\n", rx_measure_clock(MEASURE_CLK_MPLL));
pos += snprintf(buf+pos, size-pos,
"\n\nHDCP info\n\n");
pos += snprintf(buf+pos, size-pos,
"HDCP Debug Value: 0x%x\n", hdmirx_rd_dwc(DWC_HDCP_DBG));
pos += snprintf(buf+pos, size-pos,
"HDCP14 state: %d\n", rx.cur.hdcp14_state);
pos += snprintf(buf+pos, size-pos,
"HDCP22 state: %d\n", rx.cur.hdcp22_state);
if (rx.port == E_PORT0)
pos += snprintf(buf+pos, size-pos,
"Source Physical address: %d.0.0.0\n", 1);
else if (rx.port == E_PORT1)
pos += snprintf(buf+pos, size-pos,
"Source Physical address: %d.0.0.0\n", 3);
else if (rx.port == E_PORT2)
pos += snprintf(buf+pos, size-pos,
"Source Physical address: %d.0.0.0\n", 2);
else if (rx.port == E_PORT3)
pos += snprintf(buf+pos, size-pos,
"Source Physical address: %d.0.0.0\n", 4);
pos += snprintf(buf+pos, size-pos,
"HDCP22_ON: %d\n", hdcp22_on);
pos += snprintf(buf+pos, size-pos,
"HDCP22 sts: 0x%x\n", rx_hdcp22_rd_reg(0x60));
pos += snprintf(buf+pos, size-pos,
"HDCP22_capable_sts: %d\n", hdcp22_capable_sts);
pos += snprintf(buf+pos, size-pos,
"sts0x8fc: 0x%x\n", hdmirx_rd_dwc(DWC_HDCP22_STATUS));
pos += snprintf(buf+pos, size-pos,
"sts0x81c: 0x%x\n", hdmirx_rd_dwc(DWC_HDCP22_CONTROL));
return pos;
}
static void dump_phy_status(void)
{
uint32_t val0, val1, val2;
rx_pr("[PHY info]\n");
if (rx.chip_id == CHIP_ID_TL1) {
rx_get_error_cnt(&val0, &val1, &val2);
rx_pr("err cnt- ch0: %d,ch1:%d ch2:%d\n", val0, val1, val2);
rx_pr("PLL_LCK_STS(tmds valid) = 0x%x\n",
hdmirx_rd_dwc(DWC_HDMI_PLL_LCK_STS));
rx_pr("MISC_STAT0 sqo = 0x%x\n",
hdmirx_rd_top(TOP_MISC_STAT0));
rx_pr("PHY_DCHD_STAT = 0x%x\n",
rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("APLL_CNTL0 = 0x%x\n",
rd_reg_hhi(HHI_HDMIRX_APLL_CNTL0));
rx_pr("TMDS_ALIGN_STAT = 0x%x\n",
hdmirx_rd_top(TOP_TMDS_ALIGN_STAT));
rx_pr("all valid = 0x%x\n", aml_phy_tmds_valid());
}
}
static void dump_clk_status(void)
{
rx_pr("[HDMI clk info]\n");
rx_pr("top cableclk=%d\n",
rx_get_clock(TOP_HDMI_CABLECLK));
rx_pr("top audio meter clk=%d\n",
rx_get_clock(TOP_HDMI_AUDIOCLK));
rx_pr("top tmdsclk=%d\n",
rx_get_clock(TOP_HDMI_TMDSCLK));
rx_pr("cable clock = %d\n",
rx_measure_clock(MEASURE_CLK_CABLE));
rx_pr("tmds clock = %d\n",
rx_measure_clock(MEASURE_CLK_TMDS));
rx_pr("Pixel clock = %d\n",
rx_measure_clock(MEASURE_CLK_PIXEL));
rx_pr("audio clock = %d\n",
rx_measure_clock(MEASURE_CLK_AUD_PLL));
rx_pr("aud clk in = %d\n",
rx_measure_clock(MEASURE_CLK_AUD_DIV));
rx_pr("mpll clock = %d\n",
rx_measure_clock(MEASURE_CLK_MPLL));
rx_pr("esm clock = %d\n",
rx_measure_clock(MEASURE_CLK_ESM));
}
static void dump_video_status(void)
{
rx_get_video_info();
rx_pr("[HDMI info]\n");
rx_pr("colorspace %d,", rx.cur.colorspace);
rx_pr("dvi %d,", rx.cur.hw_dvi);
rx_pr("sw_dvi:%d,", rx.cur.sw_dvi);
rx_pr("interlace %d\n", rx.cur.interlaced);
rx_pr("htotal %d\n", rx.cur.htotal);
rx_pr("hactive %d\n", rx.cur.hactive);
rx_pr("vtotal %d\n", rx.cur.vtotal);
rx_pr("vactive %d\n", rx.cur.vactive);
rx_pr("repetition %d\n", rx.cur.repeat);
rx_pr("colordepth %d\n", rx.cur.colordepth);
rx_pr("frame_rate %d\n", rx.cur.frame_rate);
rx_pr("fmt=0x%x,", hdmirx_hw_get_fmt());
rx_pr("hw_vic %d,", rx.cur.hw_vic);
rx_pr("sw_vic %d,", rx.pre.sw_vic);
rx_pr("rx.no_signal=%d,rx.state=%d,",
rx.no_signal, rx.state);
rx_pr("skip frame=%d\n", rx.skip);
rx_pr("avmute_skip:0x%x\n", rx.avmute_skip);
rx_pr("phy addr: %#x,%#x,port: %d, up phy addr:%#x\n",
hdmirx_rd_top(TOP_EDID_RAM_OVR1_DATA),
hdmirx_rd_top(TOP_EDID_RAM_OVR2_DATA),
rx.port, up_phy_addr);
dump_clk_status();
rx_pr("eq=%x\n", (rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1)>>4)&0xffff);
}
static void dump_audio_status(void)
{
static struct aud_info_s a;
uint32_t val0, val1;
rx_get_audinfo(&a);
rx_pr("[AudioInfo]\n");
rx_pr(" CT=%u CC=%u", a.coding_type,
a.channel_count);
rx_pr(" SF=%u SS=%u", a.sample_frequency,
a.sample_size);
rx_pr(" CA=%u\n", a.auds_ch_alloc);
rx_pr("CTS=%d, N=%d,", a.cts, a.n);
rx_pr("acr clk=%d\n", a.arc);
if (rx.chip_id == CHIP_ID_TL1) {
rx_get_audio_N_CTS(&val0, &val1);
rx_pr("top CTS:%d, N:%d\n", val1, val0);
}
rx_pr("audio receive data:%d\n",
auds_rcv_sts);
}
static void dump_hdcp_status(void)
{
rx_pr("HDCP version:%d\n", rx.hdcp.hdcp_version);
if (hdcp22_on) {
rx_pr("HDCP22 sts = %x\n",
rx_hdcp22_rd_reg(0x60));
rx_pr("HDCP22_on = %d\n",
hdcp22_on);
rx_pr("HDCP22_auth_sts = %d\n",
hdcp22_auth_sts);
rx_pr("HDCP22_capable_sts = %d\n",
hdcp22_capable_sts);
rx_pr("video_stable_to_esm = %d\n",
video_stable_to_esm);
rx_pr("hpd_to_esm = %d\n",
hpd_to_esm);
rx_pr("sts8fc = %x",
hdmirx_rd_dwc(DWC_HDCP22_STATUS));
rx_pr("sts81c = %x",
hdmirx_rd_dwc(DWC_HDCP22_CONTROL));
}
rx_pr("ESM clock = %d\n",
rx_measure_clock(MEASURE_CLK_ESM));
rx_pr("HDCP debug value=0x%x\n",
hdmirx_rd_dwc(DWC_HDCP_DBG));
rx_pr("HDCP14 state:%d\n",
rx.cur.hdcp14_state);
rx_pr("HDCP22 state:%d\n",
rx.cur.hdcp22_state);
rx_pr("\n hdcp-seed = %d ",
rx.hdcp.seed);
/* KSV CONFIDENTIAL */
rx_pr("hdcp-bksv = %x---%x\n",
hdmirx_rd_dwc(DWC_HDCP_BKSV1),
hdmirx_rd_dwc(DWC_HDCP_BKSV0));
}
void dump_state(int enable)
{
rx_get_video_info();
if (enable == RX_DUMP_VIDEO) /* video info */
dump_video_status();
else if (enable & RX_DUMP_ALL) {
dump_clk_status();
dump_phy_status();
dump_video_status();
dump_audio_status();
dump_hdcp_status();
} else if (enable & RX_DUMP_AUDIO) /* audio info */
dump_audio_status();
else if (enable & RX_DUMP_HDCP) /* hdcp info */
dump_hdcp_status();
else if (enable & RX_DUMP_PHY) /* phy info */
dump_phy_status();
else if (enable & RX_DUMP_CLK) /* clk src info */
dump_clk_status();
else
dump_video_status();
}
void rx_debug_help(void)
{
rx_pr("*****************\n");
rx_pr("reset0--hw_config\n");
rx_pr("reset1--8bit phy rst\n");
rx_pr("reset3--irq open\n");
rx_pr("reset4--edid_update\n");
rx_pr("reset5--esm rst\n");
rx_pr("database--esm data addr\n");
rx_pr("duk--dump duk\n");
rx_pr("v - driver version\n");
rx_pr("state0 -dump video\n");
rx_pr("state1 -dump audio\n");
rx_pr("state2 -dump hdcp\n");
rx_pr("state3 -dump phy\n");
rx_pr("state4 -dump clock\n");
rx_pr("statex -dump all\n");
rx_pr("port1/2/3 -port swich\n");
rx_pr("hpd0/1 -set hpd 0:low\n");
rx_pr("cable_status -5V sts\n");
rx_pr("pause -pause fsm\n");
rx_pr("reg -dump all dwc reg\n");
rx_pr("*****************\n");
}
int hdmirx_debug(const char *buf, int size)
{
char tmpbuf[128];
int i = 0;
uint32_t value = 0;
char input[5][20];
char *const delim = " ";
char *token;
char *cur;
int cnt = 0;
unsigned char edid_index;
unsigned char *pedid_data;
struct edid_info_s edid_info;
while ((buf[i]) && (buf[i] != ',') && (buf[i] != ' ')) {
tmpbuf[i] = buf[i];
i++;
}
tmpbuf[i] = 0;
for (cnt = 0; cnt < 5; cnt++)
input[cnt][0] = '\0';
cur = (char *)buf;
cnt = 0;
while ((token = strsep(&cur, delim)) && (cnt < 5)) {
if (strlen((char *)token) < 20)
strcpy(&input[cnt][0], (char *)token);
else
rx_pr("err input\n");
cnt++;
}
if (strncmp(tmpbuf, "help", 4) == 0) {
rx_debug_help();
} else if (strncmp(tmpbuf, "hpd", 3) == 0)
rx_set_cur_hpd(tmpbuf[3] == '0' ? 0 : 1);
else if (strncmp(tmpbuf, "cable_status", 12) == 0) {
size = hdmirx_rd_top(TOP_HPD_PWR5V) >> 20;
rx_pr("cable_status = %x\n", size);
} else if (strncmp(tmpbuf, "signal_status", 13) == 0) {
size = rx.no_signal;
rx_pr("signal_status = %d\n", size);
} else if (strncmp(tmpbuf, "reset", 5) == 0) {
if (tmpbuf[5] == '0') {
rx_pr(" hdmirx hw config\n");
hdmirx_hw_config();
hdmi_rx_top_edid_update();
} else if (tmpbuf[5] == '1') {
rx_pr(" hdmirx phy init 8bit\n");
hdmirx_phy_init();
} else if (tmpbuf[5] == '3') {
rx_pr(" irq open\n");
rx_irq_en(true);
} else if (tmpbuf[5] == '4') {
rx_pr(" edid update\n");
hdmi_rx_top_edid_update();
} else if (tmpbuf[5] == '5') {
hdmirx_hdcp22_esm_rst();
}
} else if (strncmp(tmpbuf, "state", 5) == 0) {
if (tmpbuf[5] == '0')
dump_state(RX_DUMP_VIDEO);
else if (tmpbuf[5] == '1')
dump_state(RX_DUMP_AUDIO);
else if (tmpbuf[5] == '2')
dump_state(RX_DUMP_HDCP);
else if (tmpbuf[5] == '3')
dump_state(RX_DUMP_PHY);
else if (tmpbuf[5] == '4')
dump_state(RX_DUMP_CLK);
else
dump_state(RX_DUMP_ALL);
} else if (strncmp(tmpbuf, "pause", 5) == 0) {
if (kstrtou32(tmpbuf + 5, 10, &value) < 0)
return -EINVAL;
rx_pr("%s\n", value ? "pause" : "enable");
sm_pause = value;
} else if (strncmp(tmpbuf, "reg", 3) == 0) {
dump_reg();
} else if (strncmp(tmpbuf, "duk", 3) == 0) {
rx_pr("hdcp22=%d\n", rx_sec_set_duk(hdmirx_repeat_support()));
} else if (strncmp(tmpbuf, "edid", 4) == 0) {
dump_edid_reg();
} else if (strncmp(tmpbuf, "load14key", 7) == 0) {
rx_debug_loadkey();
} else if (strncmp(tmpbuf, "load22key", 9) == 0) {
rx_debug_load22key();
} else if (strncmp(tmpbuf, "esm0", 4) == 0) {
/* switch_set_state(&rx.hpd_sdev, 0x0); */
extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 0);
} else if (strncmp(tmpbuf, "esm1", 4) == 0) {
/*switch_set_state(&rx.hpd_sdev, 0x01);*/
extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 1);
} else if (strncmp(input[0], "pktinfo", 7) == 0) {
rx_debug_pktinfo(input);
} else if (strncmp(tmpbuf, "parse_edid", 10) == 0) {
edid_index = rx_get_edid_index();
pedid_data = rx_get_edid(edid_index);
memset(&edid_info, 0, sizeof(struct edid_info_s));
edid_parse_block0(pedid_data, &edid_info);
edid_parse_cea_block(pedid_data+128, &edid_info);
rx_edid_parse_print(&edid_info);
} else if (tmpbuf[0] == 'w') {
rx_debug_wr_reg(buf, tmpbuf, i);
} else if (tmpbuf[0] == 'r') {
rx_debug_rd_reg(buf, tmpbuf);
} else if (tmpbuf[0] == 'v') {
rx_pr("------------------\n");
rx_pr("Hdmirx version0: %s\n", RX_VER0);
rx_pr("Hdmirx version1: %s\n", RX_VER1);
rx_pr("Hdmirx version2: %s\n", RX_VER2);
rx_pr("------------------\n");
} else if (strncmp(input[0], "port0", 5) == 0) {
hdmirx_open_port(TVIN_PORT_HDMI0);
signal_status_init();
rx.open_fg = 1;
} else if (strncmp(input[0], "port1", 5) == 0) {
hdmirx_open_port(TVIN_PORT_HDMI1);
signal_status_init();
rx.open_fg = 1;
} else if (strncmp(input[0], "port2", 5) == 0) {
hdmirx_open_port(TVIN_PORT_HDMI2);
signal_status_init();
rx.open_fg = 1;
} else if (strncmp(input[0], "port3", 5) == 0) {
hdmirx_open_port(TVIN_PORT_HDMI3);
signal_status_init();
rx.open_fg = 1;
} else if (strncmp(input[0], "empsts", 6) == 0) {
rx_emp_status();
} else if (strncmp(input[0], "empstart", 8) == 0) {
rx_emp_capture_stop();
rx_emp_resource_allocate(hdmirx_dev);
rx_emp_to_ddr_init();
} else if (strncmp(input[0], "tmdsstart", 9) == 0) {
rx_emp_capture_stop();
rx_tmds_resource_allocate(hdmirx_dev);
rx_tmds_to_ddr_init();
} else if (strncmp(input[0], "empcapture", 10) == 0) {
rx_emp_data_capture();
} else if (strncmp(input[0], "tmdscapture", 11) == 0) {
rx_tmds_data_capture();
} else if (strncmp(input[0], "tmdscnt", 7) == 0) {
if (kstrtou32(input[1], 16, &value) < 0)
rx_pr("error input Value\n");
rx_pr("set pkt cnt:0x%x\n", value);
rx.empbuff.tmdspktcnt = value;
} else if (strncmp(input[0], "phyinit", 7) == 0) {
aml_phy_bw_switch();
} else if (strncmp(input[0], "phyeq", 5) == 0) {
//aml_eq_setting();
find_best_eq = 0x1111;
rx.phy.err_sum = 0xffffff;
} else if (strncmp(tmpbuf, "audio", 5) == 0) {
hdmirx_audio_fifo_rst();
}
return 0;
}
void hdmirx_timer_handler(unsigned long arg)
{
struct hdmirx_dev_s *devp = (struct hdmirx_dev_s *)arg;
rx_5v_monitor();
rx_check_repeat();
if (rx.open_fg) {
rx_nosig_monitor();
if (!hdmirx_repeat_support() || !rx.firm_change) {
if (!sm_pause) {
rx_clkrate_monitor();
rx_main_state_machine();
}
rx_pkt_check_content();
rx_err_monitor();
#ifdef K_TEST_CHK_ERR_CNT
if (err_chk_en)
rx_monitor_error_counter();
rx_get_best_eq_setting();
#endif
}
}
devp->timer.expires = jiffies + TIMER_STATE_CHECK;
add_timer(&devp->timer);
}