blob: 29b7423dccd4b9ac2ec678a1426726b7fa1eebaa [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#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/spinlock.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/uaccess.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/arm-smccc.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/highmem.h>
/* Local include */
#include "hdmi_rx_repeater.h"
#include "hdmi_rx_drv.h"
#include "hdmi_rx_hw.h"
#include "hdmi_rx_wrapper.h"
/* for TL1 */
static const u32 eq_debug[] = {
/* value eq gain */
0xffffffff,
0xffff1030,/* min */
0x7fff1030,
0x7f7f1030,
0x3f7f1030,
0x3f3f1030,
0x1f3f1030,
0x1f1f1030,
0x0f0f1030,/* half of all range max */
0x0f071030,
0x07071030,
0x07031030,
0x03031030,
0x03011030,
0x01011030,
0x01001030,
0x00001030,/* max */
0xffff0000,/* min */
0x7fff0000,
0x7f7f0000,
0x3f7f0000,
0x3f3f0000,
0x1f3f0000,
0x1f1f0000,
0x0f0f0000,/* half of all range max */
0x0f070000,
0x07070000,
0x07030000,
0x03030000,
0x03010000,
0x01010000,
0x01000000,
0x00000000,/* max */
};
static const u32 phy_misci[][4] = {
/* 0xd7 0xd8 0xe0 0xe1 */
{ /* 24~45M */
0x3003707f, 0x00000080, 0x02218000, 0x00000010,
},
{ /* 45~74.5M */
0x3003707f, 0x00000080, 0x02218000, 0x00000010,
},
{ /* 77~155M */
0x3003707f, 0x00000080, 0x02218000, 0x00000010,
},
{ /* 155~340M */
0x3003707f, 0x00000080, 0x02218000, 0x00000010,
},
{ /* 340~525M */
0x3003707f, 0x007f0080, 0x02218000, 0x00000010,
},
{ /* 525~600M */
0x3003707f, 0x007f8080, 0x02218000, 0x00000010,
},
};
static const u32 phy_dcha[][3] = {
/* 0xe2 0xe3 0xe4 */
{ /* 24~45M */
0x00000280, 0x4400c202, 0x030088a2,
},
{ /* 45~74.5M */
0x00000280, 0x4400c202, 0x030088a2,
},
{ /* 77~155M */
0x000002a2, 0x6800c202, 0x01009126,
},
{ /* 155~340M */
0x00000280, 0x0800c202, 0x0100cc31,
},
{ /* 340~525M */
0x00000280, 0x0700003c, 0x1d00cc31,
},
{ /* 525~600M */
0x00000280, 0x07000000, 0x1d00cc31,
},
};
static const u32 phy_dcha_reva[][3] = {
/* 0xe2 0xe3 0xe4 */
{ /* 24~45M */
0x00000280, 0x2400c202, 0x030088a2,
},
{ /* 45~74.5M */
0x00000280, 0x2400c202, 0x030088a2,
},
{ /* 77~155M */
0x000002a2, 0x4800c202, 0x01009126,
},
{ /* 155~340M */
0x000002a2, 0x0800c202, 0x0100cc31,
},
{ /* 340~525M */
0x000002a2, 0x0700003c, 0x1d00cc31,
},
{ /* 525~600M */
0x000002a2, 0x0700003c, 0x1d00cc31,
},
};
/* long cable */
static const u32 phy_dchd_1[][3] = {
/* 0xe5 0xe6 0xe7 */
{ /* 24~45M */
0x003e714a, 0x1e051630, 0x00018000,
},
{ /* 45~74.5M */
0x003e714a, 0x1e051630, 0x00018000,
},
{ /* 77~155M */
0x003c714a, 0x1e062620, 0x00018000,
},
{ /* 155~340M */
0x003c714a, 0x1e050064, 0x0001a000,
},
{ /* 340~525M */
0x003c714a, 0x1e050064, 0x0001a000,
},
{ /* 525~600M */
0x003e714a, 0x1e050560, 0x0001a000,
},
};
/* short cable */
static const u32 phy_dchd_2[][3] = {
/* 0xe5 0xe6 0xe7 */
{ /* 24~45M */
0x003e714a, 0x1e022220, 0x00018000,
},
{ /* 45~74.5M */
0x003e714a, 0x1e022220, 0x00018000,
},
{ /* 77~155M */
0x003c714a, 0x1e022220, 0x00018000,
},
{ /* 155~340M */
0x003c714a, 0x1e022220, 0x0001a000,
},
{ /* 340~525M */
0x003c714a, 0x1e040460, 0x0001a000,
},
{ /* 525~600M */
0x003e714a, 0x1e040460, 0x0001a000,
},
};
bool is_tl1_former(void)
{
if (is_meson_tl1_cpu() &&
is_meson_rev_a())
return 1;
return 0;
}
void aml_eq_cfg_tl1(void)
{
u32 data32 = 0;
u32 idx = rx.phy.phy_bw;
/* data channel release reset */
data32 = rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0);
data32 |= (0x7 << 7);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data32);
usleep_range(50, 60);
if (find_best_eq) {
data32 = phy_dchd_1[idx][1] & (~(MSK(16, 4)));
data32 |= find_best_eq << 4;
} else if ((rx.phy.cablesel % 2) == 0) {
data32 = phy_dchd_1[idx][1];
} else if ((rx.phy.cablesel % 2) == 1) {
data32 = phy_dchd_2[idx][1];
}
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
usleep_range(5, 10);
data32 |= 0x00400000;
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
}
void aml_phy_cfg_tl1(void)
{
u32 idx = rx.phy.phy_bw;
u32 data32, c1, c2, r1, r2;
u32 term_value =
hdmirx_rd_top(TOP_HPD_PWR5V) & 0x7;
c1 = eq_debug[eq_dbg_lvl] & 0xff;
c2 = (eq_debug[eq_dbg_lvl] >> 8) & 0xff;
r1 = (eq_debug[eq_dbg_lvl] >> 16) & 0xff;
r2 = (eq_debug[eq_dbg_lvl] >> 24) & 0xff;
data32 = phy_misci[idx][0];
data32 = (data32 & (~0x7));
data32 |= term_value;
data32 &= ~(disable_port_num & 0x07);
/* terminal en */
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data32);
usleep_range(2, 4);
/* data channel and common block reset */
/*update from "data channel and common block */
/* reset"to"only common block reset" */
data32 |= 0xf << 7;
/* data32 |= 0x1 << 10; */
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data32);
usleep_range(2, 4);
data32 = phy_misci[idx][1];
if (idx < PHY_BW_5 && phy_tdr_en) {
if (term_cal_en) {
data32 = (((data32 & (~(0x3ff << 12))) |
(term_cal_val << 12)) | (1 << 22));
} else {
data32 = phy_trim_val;
}
}
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL1, data32);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL2, phy_misci[idx][2]);
/* reset and select data port */
data32 = phy_misci[idx][3];
data32 |= ((1 << rx.port) << 6);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3, data32);
/* release reset */
data32 |= (1 << 11);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3, data32);
usleep_range(5, 10);
if (is_tl1_former()) {
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL0, phy_dcha_reva[idx][0]);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL1, phy_dcha_reva[idx][1]);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL2, phy_dcha_reva[idx][2]);
} else {
if (eq_dbg_lvl == 0) {
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL0, phy_dcha[idx][0]);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL1, phy_dcha[idx][1]);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL2, phy_dcha[idx][2]);
} else {
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL0,
(phy_dcha[idx][0] | (c1 << 10) | (c2 << 18) | (r1 << 26)));
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL1,
(phy_dcha[idx][1] | (r1 >> 6)) | (r2 << 2));
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL2,
(phy_dcha[idx][2] & (~(1 << 24))));
}
}
if (cdr_lock_level == 0)
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL0, phy_dchd_1[idx][0]);
else if (cdr_lock_level == 1)
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL0, 0x006f0041);
else if (cdr_lock_level == 2)
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL0, 0x002f714a);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL2, phy_dchd_1[idx][2]);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL2, phy_dchd_1[idx][2]);
if ((rx.phy.cablesel % 2) == 0)
data32 = phy_dchd_1[idx][1];
else if ((rx.phy.cablesel % 2) == 1)
data32 = phy_dchd_2[idx][1];
/* wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32); */
usleep_range(5, 10);
/*data32 |= 0x00400000;*/
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);/*398*/
}
struct apll_param apll_tab_tl1[] = {
/*od for tmds: 2/4/8/16/32*/
/*od2 for audio: 1/2/4/8/16*/
/* bw M, N, od, od_div, od2, od2_div, aud_div */
/* {PLL_BW_0, 160, 1, 0x5, 32,0x2, 8, 2}, */
{PLL_BW_0, 160, 1, 0x5, 32, 0x1, 8, 3},/* 16 x 27 */
/* {PLL_BW_1, 80, 1, 0x4, 16, 0x2, 8, 1}, */
{PLL_BW_1, 80, 1, 0x4, 16, 0x0, 8, 3},/* 8 x 74 */
/* {PLL_BW_2, 40, 1, 0x3, 8, 0x2, 8, 0}, */
{PLL_BW_2, 40, 1, 0x3, 8, 0x0, 8, 2}, /* 4 x 148 */
/* {PLL_BW_3, 40, 2, 0x2, 4, 0x1, 4, 0}, */
{PLL_BW_3, 40, 2, 0x2, 4, 0x0, 4, 1},/* 2 x 297 */
/* {PLL_BW_4, 40, 1, 0x1, 2, 0x0, 2, 0}, */
{PLL_BW_4, 40, 1, 0x1, 2, 0x0, 2, 0},/* 594 */
{PLL_BW_NULL, 40, 1, 0x3, 8, 0x2, 8, 0},
};
void aml_pll_bw_cfg_tl1(void)
{
u32 M, N;
u32 od, od_div;
u32 od2, od2_div;
u32 bw = rx.phy.pll_bw;
u32 vco_clk;
u32 data, data2;
u32 cableclk = rx.clk.cable_clk / KHz;
int pll_rst_cnt = 0;
od_div = apll_tab_tl1[bw].od_div;
od = apll_tab_tl1[bw].od;
M = apll_tab_tl1[bw].M;
N = apll_tab_tl1[bw].N;
od2_div = apll_tab_tl1[bw].od2_div;
od2 = apll_tab_tl1[bw].od2;
/*set audio pll divider*/
rx.phy.aud_div = apll_tab_tl1[bw].aud_div;
vco_clk = (cableclk * M) / N; /*KHz*/
if ((vco_clk < (2970 * KHz)) || (vco_clk > (6000 * KHz))) {
if (log_level & VIDEO_LOG)
rx_pr("err: M=%d,N=%d,vco_clk=%d\n", M, N, vco_clk);
}
if (is_tl1_former())
od2 += 1;
do {
/*cntl0 M <7:0> N<14:10>*/
data = 0x00090400 & 0xffff8300;
data |= M;
data |= (N << 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, data | 0x20000000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, data | 0x30000000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL1, 0x00000000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL2, 0x00001118);
usleep_range(5, 10);
data2 = 0x10058f30 | od2;
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL3, data2);
if (is_tl1_former())
data2 = 0x000100c0;
else
data2 = 0x080130c0;
data2 |= (od << 24);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL4, data2);
usleep_range(5, 10);
/*apll_vctrl_mon_en*/
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL4, data2 | 0x00800000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, data | 0x34000000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, data | 0x14000000);
usleep_range(5, 10);
/* bit'5: force lock bit'2: improve phy ldo voltage */
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL2, 0x0000303c);
usleep_range(100, 110);
if (pll_rst_cnt++ > pll_rst_max) {
rx_pr("pll rst error\n");
break;
}
if (log_level & VIDEO_LOG)
rx_pr("pll init-cableclk=%d,pixelclk=%d,sq=%d\n",
rx.clk.cable_clk / MHz,
rx.clk.pixel_clk / MHz,
hdmirx_rd_top(TOP_MISC_STAT0) & 0x1);
} while ((!is_tmds_clk_stable()) && is_clk_stable());
/* data channel reset */
data = rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0);
data &= (~(0x7 << 7));
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data);
}
/*
* aml phy initial
*/
//For TL1 and TM2 rev1
void aml_phy_init_tl1(void)
{
aml_phy_cfg_tl1();
usleep_range(100, 110);
aml_pll_bw_cfg_tl1();
usleep_range(100, 110);
aml_eq_cfg_tl1();
}
void dump_reg_phy_tl1_tm2(void)
{
rx_pr("PHY Register:\n");
rx_pr("0xd2(348)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_APLL_CNTL0));
rx_pr("0xd3(34c)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_APLL_CNTL1));
rx_pr("0xd4(350)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_APLL_CNTL2));
rx_pr("0xd5(354)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_APLL_CNTL3));
rx_pr("0xd6(358)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_APLL_CNTL4));
rx_pr("0xd7(35c)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0));
rx_pr("0xd8(360)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL1));
rx_pr("0xe0(380)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL2));
rx_pr("0xe1(384)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3));
rx_pr("0xe2(388)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL0));
rx_pr("0xe3(38c)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL1));
rx_pr("0xe4(390)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL2));
rx_pr("0xc5(314)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL3));
rx_pr("0xe5(394)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL0));
rx_pr("0xe6(398)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1));
rx_pr("0xe7(39c)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL2));
rx_pr("0xc6(318)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL3));
/*rx_pr("0xe8(3a0)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_ARC_CNTL));*/
rx_pr("0xee(3b8)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_MISC_STAT));
rx_pr("0xef(3bc)=0x%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
}
void dump_aml_phy_sts_tl1(void)
{
u32 val0, val1, val2, data32;
rx_pr("[PHY info]\n");
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_get_tmds_valid_tl1());
data32 = rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1);
data32 = data32 & 0xf0ffffff;
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
rx_pr("0x3bc-0=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
usleep_range(100, 110);
data32 = ((data32 & 0xf0ffffff) | (0x2 << 24));
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
rx_pr("0x3bc-2=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
usleep_range(100, 110);
data32 = ((data32 & 0xf0ffffff) | (0x4 << 24));
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
rx_pr("0x3bc-4=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
usleep_range(100, 110);
data32 = ((data32 & 0xf0ffffff) | (0x6 << 24));
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
rx_pr("0x3bc-6=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
usleep_range(100, 110);
data32 = ((data32 & 0xf0ffffff) | (0xe << 24));
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, data32);
if (log_level & VIDEO_LOG) {
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
rx_pr("0x3bc-e=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_DCHD_STAT));
}
}
void aml_phy_short_bist_tl1(void)
{
int data32;
int bist_mode = 3;
int port;
int ch0_lock = 0;
int ch1_lock = 0;
int ch2_lock = 0;
int lock_sts = 0;
rx_pr("bist start\n");
for (port = 0; port < 3; port++) {
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, 0x10034079);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, 0x100347f9);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL1, 0x007f8fc0);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL2, 0x02200000);
usleep_range(5, 10);
data32 = 0;
/*selector clock to digital from data ch*/
data32 |= (1 << port) << 3;
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3, data32);
rx_pr("\nport=%x\n", rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3));
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL0, 0x000002a2);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL1, 0x07000000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL2, 0x1d00cc31);//0x1d004451
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL0, 0x003e714a);//0x002c714a
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, 0x1e040460);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL2, 0x00018000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, 0x200904f8);
usleep_range(100, 110);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, 0x300904f8);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL1, 0x00000000);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL2, 0x00001108);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL3, 0x10058f30);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL4, 0x090100c0);
usleep_range(100, 110);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL4, 0x098100c0);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, 0x340904f8);
usleep_range(100, 110);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL0, 0x140904f8);
usleep_range(5, 10);
wr_reg_hhi(HHI_HDMIRX_APLL_CNTL2, 0x00003008);
usleep_range(100, 110);
/* Reset */
data32 = 0x0;
data32 |= 1 << 8;
data32 |= 1 << 7;
/* Configure BIST analyzer before BIST path out of reset */
hdmirx_wr_top(TOP_SW_RESET, data32);
usleep_range(5, 10);
// Configure BIST analyzer before BIST path out of reset
data32 = 0;
// [23:22] prbs_ana_ch2_prbs_mode:
// 0=prbs11; 1=prbs15; 2=prbs7; 3=prbs31.
data32 |= bist_mode << 22;
// [21:20] prbs_ana_ch2_width:3=10-bit pattern
data32 |= 3 << 20;
// [ 19] prbs_ana_ch2_clr_ber_meter //0
data32 |= 1 << 19;
// [ 18] prbs_ana_ch2_freez_ber
data32 |= 0 << 18;
// [ 17] prbs_ana_ch2_bit_reverse
data32 |= 1 << 17;
// [15:14] prbs_ana_ch1_prbs_mode:
// 0=prbs11; 1=prbs15; 2=prbs7; 3=prbs31.
data32 |= bist_mode << 14;
// [13:12] prbs_ana_ch1_width:3=10-bit pattern
data32 |= 3 << 12;
// [ 11] prbs_ana_ch1_clr_ber_meter //0
data32 |= 1 << 11;
// [ 10] prbs_ana_ch1_freez_ber
data32 |= 0 << 10;
// [ 9] prbs_ana_ch1_bit_reverse
data32 |= 1 << 9;
// [ 7: 6] prbs_ana_ch0_prbs_mode:
// 0=prbs11; 1=prbs15; 2=prbs7; 3=prbs31.
data32 |= bist_mode << 6;
// [ 5: 4] prbs_ana_ch0_width:3=10-bit pattern
data32 |= 3 << 4;
// [ 3] prbs_ana_ch0_clr_ber_meter //0
data32 |= 1 << 3;
// [ 2] prbs_ana_ch0_freez_ber
data32 |= 0 << 2;
// [ 1] prbs_ana_ch0_bit_reverse
data32 |= 1 << 1;
hdmirx_wr_top(TOP_PRBS_ANA_0, data32);
usleep_range(5, 10);
data32 = 0;
// [19: 8] prbs_ana_time_window
data32 |= 255 << 8;
// [ 7: 0] prbs_ana_err_thr
data32 |= 0;
hdmirx_wr_top(TOP_PRBS_ANA_1, data32);
usleep_range(5, 10);
// Configure channel switch
data32 = 0;
data32 |= 2 << 28;// [29:28] source_2
data32 |= 1 << 26;// [27:26] source_1
data32 |= 0 << 24;// [25:24] source_0
data32 |= 0 << 22;// [22:20] skew_2
data32 |= 0 << 16;// [18:16] skew_1
data32 |= 0 << 12;// [14:12] skew_0
data32 |= 0 << 10;// [ 10] bitswap_2
data32 |= 0 << 9;// [ 9] bitswap_1
data32 |= 0 << 8;// [ 8] bitswap_0
data32 |= 0 << 6;// [ 6] polarity_2
data32 |= 0 << 5;// [ 5] polarity_1
data32 |= 0 << 4;// [ 4] polarity_0
data32 |= 0;// [ 0] enable
hdmirx_wr_top(TOP_CHAN_SWITCH_0, data32);
usleep_range(5, 10);
// Configure BIST generator
data32 = 0;
data32 |= 0 << 8;// [ 8] bist_loopback
data32 |= 3 << 5;// [ 7: 5] decoup_thresh
// [ 4: 3] prbs_gen_mode:0=prbs11; 1=prbs15; 2=prbs7; 3=prbs31.
data32 |= bist_mode << 3;
data32 |= 3 << 1;// [ 2: 1] prbs_gen_width:3=10-bit.
data32 |= 0;// [ 0] prbs_gen_enable
hdmirx_wr_top(TOP_PRBS_GEN, data32);
usleep_range(100, 110);
/* Reset */
data32 = 0x0;
data32 &= ~(1 << 8);
data32 &= ~(1 << 7);
/* Configure BIST analyzer before BIST path out of reset */
hdmirx_wr_top(TOP_SW_RESET, data32);
usleep_range(100, 110);
// Configure channel switch
data32 = 0;
data32 |= 2 << 28;// [29:28] source_2
data32 |= 1 << 26;// [27:26] source_1
data32 |= 0 << 24;// [25:24] source_0
data32 |= 0 << 22;// [22:20] skew_2
data32 |= 0 << 16;// [18:16] skew_1
data32 |= 0 << 12;// [14:12] skew_0
data32 |= 0 << 10;// [ 10] bitswap_2
data32 |= 0 << 9;// [ 9] bitswap_1
data32 |= 0 << 8;// [ 8] bitswap_0
data32 |= 0 << 6;// [ 6] polarity_2
data32 |= 0 << 5;// [ 5] polarity_1
data32 |= 0 << 4;// [ 4] polarity_0
data32 |= 1;// [ 0] enable
hdmirx_wr_top(TOP_CHAN_SWITCH_0, data32);
/* Configure BIST generator */
data32 = 0;
/* [ 8] bist_loopback */
data32 |= 0 << 8;
/* [ 7: 5] decoup_thresh */
data32 |= 3 << 5;
// [ 4: 3] prbs_gen_mode:
// 0=prbs11; 1=prbs15; 2=prbs7; 3=prbs31.
data32 |= bist_mode << 3;
/* [ 2: 1] prbs_gen_width:3=10-bit. */
data32 |= 3 << 1;
/* [ 0] prbs_gen_enable */
data32 |= 1;
hdmirx_wr_top(TOP_PRBS_GEN, data32);
/* PRBS analyzer control */
hdmirx_wr_top(TOP_PRBS_ANA_0, 0xf6f6f6);
usleep_range(100, 110);
hdmirx_wr_top(TOP_PRBS_ANA_0, 0xf2f2f2);
//if ((hdmirx_rd_top(TOP_PRBS_GEN) & data32) != 0)
//return;
usleep_range(5000, 5050);
/* Check BIST analyzer BER counters */
if (port == 0)
rx_pr("BER_CH0 = %x\n", hdmirx_rd_top(TOP_PRBS_ANA_BER_CH0));
else if (port == 1)
rx_pr("BER_CH1 = %x\n", hdmirx_rd_top(TOP_PRBS_ANA_BER_CH1));
else if (port == 2)
rx_pr("BER_CH2 = %x\n", hdmirx_rd_top(TOP_PRBS_ANA_BER_CH2));
/* check BIST analyzer result */
lock_sts = hdmirx_rd_top(TOP_PRBS_ANA_STAT) & 0x3f;
rx_pr("ch%dsts=0x%x\n", port, lock_sts);
if (port == 0) {
ch0_lock = lock_sts & 3;
if (ch0_lock == 1)
rx_pr("ch0 PASS\n");
else
rx_pr("ch0 NG\n");
}
if (port == 1) {
ch1_lock = (lock_sts >> 2) & 3;
if (ch1_lock == 1)
rx_pr("ch1 PASS\n");
else
rx_pr("ch1 NG\n");
}
if (port == 2) {
ch2_lock = (lock_sts >> 4) & 3;
if (ch2_lock == 1)
rx_pr("ch2 PASS\n");
else
rx_pr("ch2 NG\n");
}
usleep_range(1000, 1010);
}
lock_sts = ch0_lock | (ch1_lock << 2) | (ch2_lock << 4);
if (lock_sts == 0x15)/* lock_sts == b'010101' is PASS*/
rx_pr("bist_test PASS\n");
else
rx_pr("bist_test FAIL\n");
rx_pr("bist done\n");
}
bool aml_get_tmds_valid_tl1(void)
{
unsigned int tmdsclk_valid;
unsigned int sqofclk;
/* unsigned int pll_lock; */
unsigned int tmds_align;
u32 ret;
/* digital tmds valid depends on PLL lock from analog phy. */
/* it is not necessary and T7 has not it */
/* tmds_valid = hdmirx_rd_dwc(DWC_HDMI_PLL_LCK_STS) & 0x01; */
sqofclk = hdmirx_rd_top(TOP_MISC_STAT0) & 0x1;
tmdsclk_valid = is_tmds_clk_stable();
tmds_align = hdmirx_rd_top(TOP_TMDS_ALIGN_STAT) & 0x3f000000;
if (sqofclk && tmdsclk_valid && tmds_align == 0x3f000000) {
ret = 1;
} else {
if (log_level & VIDEO_LOG) {
rx_pr("sqo:%x,tmdsclk_valid:%x,align:%x\n",
sqofclk, tmdsclk_valid, tmds_align);
rx_pr("cable clk0:%d\n", rx.clk.cable_clk);
rx_pr("cable clk1:%d\n", rx_get_clock(TOP_HDMI_CABLECLK));
}
ret = 0;
}
return ret;
}
void aml_phy_power_off_tl1(void)
{
/* pll power down */
wr_reg_hhi_bits(HHI_HDMIRX_APLL_CNTL0, MSK(2, 28), 2);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, 0x32037800);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL1, 0x1000000);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL2, 0x62208002);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3, 0x7);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL0, 0x1e);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHA_CNTL1, 0x10000800);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL0, 0x200000);
wr_reg_hhi(HHI_HDMIRX_PHY_DCHD_CNTL1, 0x0);
}
void aml_phy_switch_port_tl1(void)
{
u32 data32;
/* reset and select data port */
data32 = rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3);
data32 &= (~(0x7 << 6));
data32 |= ((1 << rx.port) << 6);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3, data32);
data32 &= (~(1 << 11));
/* release reset */
data32 |= (1 << 11);
wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL3, data32);
udelay(5);
data32 = 0;
data32 |= rx.port << 2;
hdmirx_wr_dwc(DWC_SNPS_PHYG3_CTRL, data32);
}