From 7ea7d4abfd537230da58533803a2d0257addace8 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 30 Mar 2022 00:46:07 -0500 Subject: [PATCH 009/117] drm/sun4i: Copy in BSP code for D1 HDMI PHY Signed-off-by: Samuel Holland --- drivers/gpu/drm/sun4i/aw_phy.h | 411 +++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 1 + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 156 ++++++++++ 3 files changed, 568 insertions(+) create mode 100644 drivers/gpu/drm/sun4i/aw_phy.h --- /dev/null +++ b/drivers/gpu/drm/sun4i/aw_phy.h @@ -0,0 +1,411 @@ +/* + * Allwinner SoCs hdmi2.0 driver. + * + * Copyright (C) 2016 Allwinner. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef AW_PHY_H_ +#define AW_PHY_H_ + +#define AW_PHY_TIMEOUT 1000 +#define LOCK_TIMEOUT 100 + +/* allwinner phy register offset */ +#define HDMI_PHY_CTL0 0x40 +#define HDMI_PHY_CTL1 0x44 +#define HDMI_PHY_CTL2 0x48 +#define HDMI_PHY_CTL3 0x4C +#define HDMI_PHY_CTL4 0x50 +#define HDMI_PHY_CTL5 0x54 +#define HDMI_PLL_CTL0 0x58 +#define HDMI_PLL_CTL1 0x5C +#define HDMI_AFIFO_CFG 0x60 +#define HDMI_MODULATOR_CFG0 0x64 +#define HDMI_MODULATOR_CFG1 0x68 +#define HDMI_PHY_INDEB_CTRL 0x6C +#define HDMI_PHY_INDBG_TXD0 0x70 +#define HDMI_PHY_INDBG_TXD1 0x74 +#define HDMI_PHY_INDBG_TXD2 0x78 +#define HDMI_PHY_INDBG_TXD3 0x7C +#define HDMI_PHY_PLL_STS 0x80 +#define HDMI_PRBS_CTL 0x84 +#define HDMI_PRBS_SEED_GEN 0x88 +#define HDMI_PRBS_SEED_CHK 0x8C +#define HDMI_PRBS_SEED_NUM 0x90 +#define HDMI_PRBS_CYCLE_NUM 0x94 +#define HDMI_PHY_PLL_ODLY_CFG 0x98 +#define HDMI_PHY_CTL6 0x9C +#define HDMI_PHY_CTL7 0xA0 + +typedef union { + u32 dwval; + struct { + u32 sda_en :1; // Default: 0; + u32 scl_en :1; // Default: 0; + u32 hpd_en :1; // Default: 0; + u32 res0 :1; // Default: 0; + u32 reg_ck_sel :1; // Default: 1; + u32 reg_ck_test_sel :1; // Default: 1; + u32 reg_csmps :2; // Default: 0; + u32 reg_den :4; // Default: F; + u32 reg_plr :4; // Default: 0; + u32 enck :1; // Default: 1; + u32 enldo_fs :1; // Default: 1; + u32 enldo :1; // Default: 1; + u32 res1 :1; // Default: 1; + u32 enbi :4; // Default: F; + u32 entx :4; // Default: F; + u32 async_fifo_autosync_disable :1; // Default: 0; + u32 async_fifo_workc_enable :1; // Default: 1; + u32 phy_pll_lock_mode :1; // Default: 1; + u32 phy_pll_lock_mode_man :1; // Default: 1; + } bits; +} HDMI_PHY_CTL0_t; //=========================== 0x0040 + +typedef union { + u32 dwval; + struct { + u32 reg_sp2_0 : 4 ; // Default: 0; + u32 reg_sp2_1 : 4 ; // Default: 0; + u32 reg_sp2_2 : 4 ; // Default: 0; + u32 reg_sp2_3 : 4 ; // Default: 0; + u32 reg_bst0 : 2 ; // Default: 3; + u32 reg_bst1 : 2 ; // Default: 3; + u32 reg_bst2 : 2 ; // Default: 3; + u32 res0 : 2 ; // Default: 0; + u32 reg_svr : 2 ; // Default: 2; + u32 reg_swi : 1 ; // Default: 0; + u32 res_scktmds : 1 ; // Default: 0; + u32 res_res_s : 2 ; // Default: 3; + u32 phy_rxsense_mode : 1 ; // Default: 0; + u32 res_rxsense_mode_man : 1 ; // Default: 0; + } bits; +} HDMI_PHY_CTL1_t; //===================================================== 0x0044 + +typedef union { + u32 dwval; + struct { + u32 reg_p2opt : 4 ; // Default: 0; + u32 reg_sp1_0 : 5 ; // Default: 0; + u32 reg_sp1_1 : 5 ; // Default: 0; + u32 reg_sp1_2 : 5 ; // Default: 0; + u32 reg_sp1_3 : 5 ; // Default: 0; + u32 reg_resdi : 6 ; // Default: 18; + u32 phy_hpdo_mode : 1 ; // Default: 0; + u32 phy_hpdo_mode_man : 1 ; // Default: 0; + } bits; +} HDMI_PHY_CTL2_t; //===================================================== 0x0048 + + + +typedef union { + u32 dwval; + struct { + u32 reg_mc0 : 4 ; // Default: F; + u32 reg_mc1 : 4 ; // Default: F; + u32 reg_mc2 : 4 ; // Default: F; + u32 reg_mc3 : 4 ; // Default: F; + u32 reg_p2_0 : 4 ; // Default: F; + u32 reg_p2_1 : 4 ; // Default: F; + u32 reg_p2_2 : 4 ; // Default: F; + u32 reg_p2_3 : 4 ; // Default: F; + } bits; +} HDMI_PHY_CTL3_t; //===================================================== 0x004C + + + +typedef union { + u32 dwval; + struct { + u32 reg_p1_0 : 5 ; // Default: 0x10; + u32 res0 : 3 ; // Default: 0; + u32 reg_p1_1 : 5 ; // Default: 0x10; + u32 res1 : 3 ; // Default: 0; + u32 reg_p1_2 : 5 ; // Default: 0x10; + u32 res2 : 3 ; // Default: 0; + u32 reg_p1_3 : 5 ; // Default: 0x10; + u32 reg_slv : 3 ; // Default: 0; + } bits; +} HDMI_PHY_CTL4_t; //===================================================== 0x0050 + +typedef union { + u32 dwval; + struct { + u32 encalog : 1 ; // Default: 0x1; + u32 enib : 1 ; // Default: 0x1; + u32 res0 : 2 ; // Default: 0; + u32 enp2s : 4 ; // Default: 0xF; + u32 enrcal : 1 ; // Default: 0x1; + u32 enres : 1 ; // Default: 1; + u32 enresck : 1 ; // Default: 1; + u32 reg_calsw : 1 ; // Default: 0; + u32 reg_ckpdlyopt : 1 ; // Default: 0; + u32 res1 : 3 ; // Default: 0; + u32 reg_p1opt : 4 ; // Default: 0; + u32 res2 : 12 ; // Default: 0; + } bits; +} HDMI_PHY_CTL5_t; //===================================================== 0x0054 + +typedef union { + u32 dwval; + struct { + u32 prop_cntrl : 3 ; // Default: 0x7; + u32 res0 : 1 ; // Default: 0; + u32 gmp_cntrl : 2 ; // Default: 1; + u32 n_cntrl : 2 ; // Default: 0; + u32 vcorange : 1 ; // Default: 0; + u32 sdrven : 1 ; // Default: 0; + u32 divx1 : 1 ; // Default: 0; + u32 res1 : 1 ; // Default: 0; + u32 div_pre : 4 ; // Default: 0; + u32 div2_cktmds : 1 ; // Default: 1; + u32 div2_ckbit : 1 ; // Default: 1; + u32 cutfb : 1 ; // Default: 0; + u32 res2 : 1 ; // Default: 0; + u32 clr_dpth : 2 ; // Default: 0; + u32 bypass_clrdpth : 1 ; // Default: 0; + u32 bcr : 1 ; // Default: 0; + u32 slv : 3 ; // Default: 4; + u32 res3 : 1 ; // Default: 0; + u32 envbs : 1 ; // Default: 0; + u32 bypass_ppll : 1 ; // Default: 0; + u32 cko_sel : 2 ; // Default: 0; + } bits; +} HDMI_PLL_CTL0_t; //===================================================== 0x0058 + + + +typedef union { + u32 dwval; + struct { + u32 int_cntrl : 3 ; // Default: 0x0; + u32 res0 : 1 ; // Default: 0; + u32 ref_cntrl : 2 ; // Default: 3; + u32 gear_shift : 1 ; // Default: 0; + u32 fast_tech : 1 ; // Default: 0; + u32 drv_ana : 1 ; // Default: 1; + u32 sckfb : 1 ; // Default: 0; + u32 sckref : 1 ; // Default: 0; + u32 reset : 1 ; // Default: 0; + u32 pwron : 1 ; // Default: 0; + u32 res1 : 3 ; // Default: 0; + u32 pixel_rep : 2 ; // Default: 0; + u32 sdm_en : 1 ; // Default: 0; + u32 pcnt_en : 1 ; // Default: 0; + u32 pcnt_n : 8 ; // Default: 0xE; + u32 res2 : 3 ; // Default: 0; + u32 ctrl_modle_clksrc : 1 ; // Default: 0; + } bits; +} HDMI_PLL_CTL1_t; //===================================================== 0x005C + +typedef union { + u32 dwval; + struct { + u32 hdmi_afifo_error : 1 ; // Default: 0x0; + u32 hdmi_afifo_error_det : 1 ; // Default: 0x0; + u32 res0 : 30 ; // Default: 0; + } bits; +} HDMI_AFIFO_CFG_t; //===================================================== 0x0060 + +typedef union { + u32 dwval; + struct { + u32 fnpll_mash_en : 1 ; // Default: 0x0; + u32 fnpll_mash_mod : 2 ; // Default: 0x0; + u32 fnpll_mash_stp : 9 ; // Default: 0x0; + u32 fnpll_mash_m12 : 1 ; // Default: 0x0; + u32 fnpll_mash_frq : 2 ; // Default: 0x0; + u32 fnpll_mash_bot : 17 ; // Default: 0x0; + } bits; +} HDMI_MODULATOR_CFG0_t; //===================================================== 0x0064 + +typedef union { + u32 dwval; + struct { + u32 fnpll_mash_dth : 1 ; // Default: 0x0; + u32 fnpll_mash_fen : 1 ; // Default: 0x0; + u32 fnpll_mash_frc : 17 ; // Default: 0x0; + u32 fnpll_mash_fnv : 8 ; // Default: 0x0; + u32 res0 : 5 ; // Default: 0x0; + } bits; +} HDMI_MODULATOR_CFG1_t; //===================================================== 0x0068 + +typedef union { + u32 dwval; + struct { + u32 txdata_debugmode : 2 ; // Default: 0x0; + u32 res0 : 14 ; // Default: 0x0; + u32 ceci_debug : 1 ; // Default: 0x0; + u32 ceci_debugmode : 1 ; // Default: 0x0; + u32 res1 : 2 ; // Default: 0x0; + u32 sdai_debug : 1 ; // Default: 0x0; + u32 sdai_debugmode : 1 ; // Default: 0x0; + u32 res2 : 2 ; // Default: 0x0; + u32 scli_debug : 1 ; // Default: 0x0; + u32 scli_debugmode : 1 ; // Default: 0x0; + u32 res3 : 2 ; // Default: 0x0; + u32 hpdi_debug : 1 ; // Default: 0x0; + u32 hpdi_debugmode : 1 ; // Default: 0x0; + u32 res4 : 2 ; // Default: 0x0; + } bits; +} HDMI_PHY_INDBG_CTRL_t; //================================================== 0x006C + +typedef union { + u32 dwval; + struct { + u32 txdata0_debug_data : 32 ; // Default: 0x0; + } bits; +} HDMI_PHY_INDBG_TXD0_t; //================================================== 0x0070 + +typedef union { + u32 dwval; + struct { + u32 txdata1_debug_data : 32 ; // Default: 0x0; + } bits; +} HDMI_PHY_INDBG_TXD1_t; //================================================== 0x0074 + +typedef union { + u32 dwval; + struct { + u32 txdata2_debug_data : 32 ; // Default: 0x0; + } bits; +} HDMI_PHY_INDBG_TXD2_t; //================================================== 0x0078 + +typedef union { + u32 dwval; + struct { + u32 txdata3_debug_data : 32 ; // Default: 0x0; + } bits; +} HDMI_PHY_INDBG_TXD3_t; //================================================== 0x007C + +typedef union { + u32 dwval; + struct { + u32 tx_ready_dly_status : 1 ; // Default: 0x0; + u32 rxsense_dly_status : 1 ; // Default: 0x0; + u32 res0 : 2 ; // Default: 0x0; + u32 pll_lock_status : 1 ; // Default: 0x0; + u32 res1 : 3 ; // Default: 0x0; + u32 phy_resdo2d_status : 6 ; // Default: 0x0; + u32 res2 : 2 ; // Default: 0x0; + u32 phy_rcalend2d_status : 1 ; // Default: 0x0; + u32 phy_cout2d_status : 1 ; // Default: 0x0; + u32 res3 : 2 ; // Default: 0x0; + u32 phy_ceco_status : 1 ; // Default: 0x0; + u32 phy_sdao_status : 1 ; // Default: 0x0; + u32 phy_sclo_status : 1 ; // Default: 0x0; + u32 phy_hpdo_status : 1 ; // Default: 0x0; + u32 phy_cdetn_status : 3 ; // Default: 0x0; + u32 phy_cdetnck_status : 1 ; // Default: 0x0; + u32 phy_cdetp_status : 3 ; // Default: 0x0; + u32 phy_cdetpck_status : 1 ; // Default: 0x0; + } bits; +} HDMI_PHY_PLL_STS_t; //===================================================== 0x0080 + +typedef union { + u32 dwval; + struct { + u32 prbs_en : 1 ; // Default: 0x0; + u32 prbs_start : 1 ; // Default: 0x0; + u32 prbs_seq_gen : 1 ; // Default: 0x0; + u32 prbs_seq_chk : 1 ; // Default: 0x0; + u32 prbs_mode : 4 ; // Default: 0x0; + u32 prbs_type : 2 ; // Default: 0x0; + u32 prbs_clk_pol : 1 ; // Default: 0x0; + u32 res0 : 21 ; // Default: 0x0; + } bits; +} HDMI_PRBS_CTL_t; //===================================================== 0x0084 + +typedef union { + u32 dwval; + struct { + u32 prbs_seed_gen : 32 ; // Default: 0x0; + } bits; +} HDMI_PRBS_SEED_GEN_t; //================================================= 0x0088 + +typedef union { + u32 dwval; + struct { + u32 prbs_seed_chk : 32 ; // Default: 0x0; + } bits; +} HDMI_PRBS_SEED_CHK_t; //================================================= 0x008C + +typedef union { + u32 dwval; + struct { + u32 prbs_seed_num : 32 ; // Default: 0x0; + } bits; +} HDMI_PRBS_SEED_NUM_t; //================================================= 0x0090 + +typedef union { + u32 dwval; + struct { + u32 prbs_cycle_num : 32 ; // Default: 0x0; + } bits; +} HDMI_PRBS_CYCLE_NUM_t; //================================================= 0x0094 + +typedef union { + u32 dwval; + struct { + u32 tx_ready_dly_count : 15 ; // Default: 0x0; + u32 tx_ready_dly_reset : 1 ; // Default: 0x0; + u32 rxsense_dly_count : 15 ; // Default: 0x0; + u32 rxsense_dly_reset : 1 ; // Default: 0x0; + } bits; +} HDMI_PHY_PLL_ODLY_CFG_t; //================================================= 0x0098 + +typedef union { + u32 dwval; + struct { + u32 clk_greate0_340m : 10 ; // Default: 0x3FF; + u32 clk_greate1_340m : 10 ; // Default: 0x3FF; + u32 clk_greate2_340m : 10 ; // Default: 0x3FF; + u32 en_ckdat : 1 ; // Default: 0x3FF; + u32 switch_clkch_data_corresponding : 1 ; // Default: 0x3FF; + } bits; +} HDMI_PHY_CTL6_t; //========================================================= 0x009C + +typedef union { + u32 dwval; + struct { + u32 clk_greate3_340m : 10 ; // Default: 0x0; + u32 res0 : 2 ; // Default: 0x3FF; + u32 clk_low_340m : 10 ; // Default: 0x3FF; + u32 res1 : 10 ; // Default: 0x3FF; + } bits; +} HDMI_PHY_CTL7_t; //========================================================= 0x00A0 + +struct __aw_phy_reg_t { + u32 res[16]; /* 0x0 ~ 0x3c */ + HDMI_PHY_CTL0_t phy_ctl0; /* 0x0040 */ + HDMI_PHY_CTL1_t phy_ctl1; /* 0x0044 */ + HDMI_PHY_CTL2_t phy_ctl2; /* 0x0048 */ + HDMI_PHY_CTL3_t phy_ctl3; /* 0x004c */ + HDMI_PHY_CTL4_t phy_ctl4; /* 0x0050 */ + HDMI_PHY_CTL5_t phy_ctl5; /* 0x0054 */ + HDMI_PLL_CTL0_t pll_ctl0; /* 0x0058 */ + HDMI_PLL_CTL1_t pll_ctl1; /* 0x005c */ + HDMI_AFIFO_CFG_t afifo_cfg; /* 0x0060 */ + HDMI_MODULATOR_CFG0_t modulator_cfg0; /* 0x0064 */ + HDMI_MODULATOR_CFG1_t modulator_cfg1; /* 0x0068 */ + HDMI_PHY_INDBG_CTRL_t phy_indbg_ctrl; /* 0x006c */ + HDMI_PHY_INDBG_TXD0_t phy_indbg_txd0; /* 0x0070 */ + HDMI_PHY_INDBG_TXD1_t phy_indbg_txd1; /* 0x0074 */ + HDMI_PHY_INDBG_TXD2_t phy_indbg_txd2; /* 0x0078 */ + HDMI_PHY_INDBG_TXD3_t phy_indbg_txd3; /* 0x007c */ + HDMI_PHY_PLL_STS_t phy_pll_sts; /* 0x0080 */ + HDMI_PRBS_CTL_t prbs_ctl; /* 0x0084 */ + HDMI_PRBS_SEED_GEN_t prbs_seed_gen; /* 0x0088 */ + HDMI_PRBS_SEED_CHK_t prbs_seed_chk; /* 0x008c */ + HDMI_PRBS_SEED_NUM_t prbs_seed_num; /* 0x0090 */ + HDMI_PRBS_CYCLE_NUM_t prbs_cycle_num; /* 0x0094 */ + HDMI_PHY_PLL_ODLY_CFG_t phy_pll_odly_cfg; /* 0x0098 */ + HDMI_PHY_CTL6_t phy_ctl6; /* 0x009c */ + HDMI_PHY_CTL7_t phy_ctl7; /* 0x00A0 */ +}; + +#endif /* AW_PHY_H_ */ --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h @@ -334,6 +334,7 @@ struct sun8i_hdmi_phy { struct clk *clk_pll1; struct device *dev; unsigned int rcal; + void __iomem *base; struct regmap *regs; struct reset_control *rst_phy; const struct sun8i_hdmi_phy_variant *variant; --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c @@ -9,6 +9,8 @@ #include "sun8i_dw_hdmi.h" +#include "aw_phy.h" + /* * Address can be actually any value. Here is set to same value as * it is set in BSP driver. @@ -398,11 +400,164 @@ static const struct dw_hdmi_phy_ops sun8 .setup_hpd = dw_hdmi_phy_setup_hpd, }; +static int sun20i_d1_hdmi_phy_enable(volatile struct __aw_phy_reg_t __iomem *phy_base) +{ + int i = 0, status = 0; + + pr_info("enter %s\n", __func__); + + //enib -> enldo -> enrcal -> encalog -> enbi[3:0] -> enck -> enp2s[3:0] -> enres -> enresck -> entx[3:0] + phy_base->phy_ctl4.bits.reg_slv = 4; //low power voltage 1.08V, default is 3, set 4 as well as pll_ctl0 bit [24:26] + phy_base->phy_ctl5.bits.enib = 1; + phy_base->phy_ctl0.bits.enldo = 1; + phy_base->phy_ctl0.bits.enldo_fs = 1; + phy_base->phy_ctl5.bits.enrcal = 1; + + phy_base->phy_ctl5.bits.encalog = 1; + + for (i = 0; i < AW_PHY_TIMEOUT; i++) { + udelay(5); + status = phy_base->phy_pll_sts.bits.phy_rcalend2d_status; + if (status & 0x1) { + pr_info("[%s]:phy_rcalend2d_status\n", __func__); + break; + } + } + if ((i == AW_PHY_TIMEOUT) && !status) { + pr_err("phy_rcalend2d_status Timeout !\n"); + return -1; + } + + phy_base->phy_ctl0.bits.enbi = 0xF; + for (i = 0; i < AW_PHY_TIMEOUT; i++) { + udelay(5); + status = phy_base->phy_pll_sts.bits.pll_lock_status; + if (status & 0x1) { + pr_info("[%s]:pll_lock_status\n", __func__); + break; + } + } + if ((i == AW_PHY_TIMEOUT) && !status) { + pr_err("pll_lock_status Timeout! status = 0x%x\n", status); + return -1; + } + + phy_base->phy_ctl0.bits.enck = 1; + phy_base->phy_ctl5.bits.enp2s = 0xF; + phy_base->phy_ctl5.bits.enres = 1; + phy_base->phy_ctl5.bits.enresck = 1; + phy_base->phy_ctl0.bits.entx = 0xF; + + for (i = 0; i < AW_PHY_TIMEOUT; i++) { + udelay(5); + status = phy_base->phy_pll_sts.bits.tx_ready_dly_status; + if (status & 0x1) { + pr_info("[%s]:tx_ready_status\n", __func__); + break; + } + } + if ((i == AW_PHY_TIMEOUT) && !status) { + pr_err("tx_ready_status Timeout ! status = 0x%x\n", status); + return -1; + } + + return 0; +} + static int sun20i_d1_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, const struct drm_display_info *display, const struct drm_display_mode *mode) { struct sun8i_hdmi_phy *phy = data; + volatile struct __aw_phy_reg_t __iomem *phy_base = phy->base; + int ret; + + pr_info("enter %s\n", __func__); + + /* enable all channel */ + phy_base->phy_ctl5.bits.reg_p1opt = 0xF; + + // phy_reset + phy_base->phy_ctl0.bits.entx = 0; + phy_base->phy_ctl5.bits.enresck = 0; + phy_base->phy_ctl5.bits.enres = 0; + phy_base->phy_ctl5.bits.enp2s = 0; + phy_base->phy_ctl0.bits.enck = 0; + phy_base->phy_ctl0.bits.enbi = 0; + phy_base->phy_ctl5.bits.encalog = 0; + phy_base->phy_ctl5.bits.enrcal = 0; + phy_base->phy_ctl0.bits.enldo_fs = 0; + phy_base->phy_ctl0.bits.enldo = 0; + phy_base->phy_ctl5.bits.enib = 0; + phy_base->pll_ctl1.bits.reset = 1; + phy_base->pll_ctl1.bits.pwron = 0; + phy_base->pll_ctl0.bits.envbs = 0; + + // phy_set_mpll + phy_base->pll_ctl0.bits.cko_sel = 0x3; + phy_base->pll_ctl0.bits.bypass_ppll = 0x1; + phy_base->pll_ctl1.bits.drv_ana = 1; + phy_base->pll_ctl1.bits.ctrl_modle_clksrc = 0x0; //0: PLL_video 1: MPLL + phy_base->pll_ctl1.bits.sdm_en = 0x0; //mpll sdm jitter is very large, not used for the time being + phy_base->pll_ctl1.bits.sckref = 0; //default value is 1 + phy_base->pll_ctl0.bits.slv = 4; + phy_base->pll_ctl0.bits.prop_cntrl = 7; //default value 7 + phy_base->pll_ctl0.bits.gmp_cntrl = 3; //default value 1 + phy_base->pll_ctl1.bits.ref_cntrl = 0; + phy_base->pll_ctl0.bits.vcorange = 1; + + // phy_set_div + phy_base->pll_ctl0.bits.div_pre = 0; //div7 = n+1 + phy_base->pll_ctl1.bits.pcnt_en = 0; + phy_base->pll_ctl1.bits.pcnt_n = 1; //div6 = 1 (pcnt_en=0) [div6 = n (pcnt_en = 1) note that some multiples are problematic] 4-256 + phy_base->pll_ctl1.bits.pixel_rep = 0; //div5 = n+1 + phy_base->pll_ctl0.bits.bypass_clrdpth = 0; + phy_base->pll_ctl0.bits.clr_dpth = 0; //div4 = 1 (bypass_clrdpth = 0) + //00: 2 01: 2.5 10: 3 11: 4 + phy_base->pll_ctl0.bits.n_cntrl = 1; //div + phy_base->pll_ctl0.bits.div2_ckbit = 0; //div1 = n+1 + phy_base->pll_ctl0.bits.div2_cktmds = 0; //div2 = n+1 + phy_base->pll_ctl0.bits.bcr = 0; //div3 0: [1:10] 1: [1:40] + phy_base->pll_ctl1.bits.pwron = 1; + phy_base->pll_ctl1.bits.reset = 0; + + // configure phy + /* config values taken from table */ + phy_base->phy_ctl1.dwval = ((phy_base->phy_ctl1.dwval & 0xFFC0FFFF) | /* config->phy_ctl1 */ 0x0); + phy_base->phy_ctl2.dwval = ((phy_base->phy_ctl2.dwval & 0xFF000000) | /* config->phy_ctl2 */ 0x0); + phy_base->phy_ctl3.dwval = ((phy_base->phy_ctl3.dwval & 0xFFFF0000) | /* config->phy_ctl3 */ 0xFFFF); + phy_base->phy_ctl4.dwval = ((phy_base->phy_ctl4.dwval & 0xE0000000) | /* config->phy_ctl4 */ 0xC0D0D0D); + //phy_base->pll_ctl0.dwval |= config->pll_ctl0; + //phy_base->pll_ctl1.dwval |= config->pll_ctl1; + + // phy_set_clk + phy_base->phy_ctl6.bits.switch_clkch_data_corresponding = 0; + phy_base->phy_ctl6.bits.clk_greate0_340m = 0x3FF; + phy_base->phy_ctl6.bits.clk_greate1_340m = 0x3FF; + phy_base->phy_ctl6.bits.clk_greate2_340m = 0x0; + phy_base->phy_ctl7.bits.clk_greate3_340m = 0x0; + phy_base->phy_ctl7.bits.clk_low_340m = 0x3E0; + phy_base->phy_ctl6.bits.en_ckdat = 1; //default value is 0 + + // phy_base->phy_ctl2.bits.reg_resdi = 0x18; + // phy_base->phy_ctl4.bits.reg_slv = 3; //low power voltage 1.08V, default value is 3 + + phy_base->phy_ctl1.bits.res_scktmds = 0; // + phy_base->phy_ctl0.bits.reg_csmps = 2; + phy_base->phy_ctl0.bits.reg_ck_test_sel = 0; //? + phy_base->phy_ctl0.bits.reg_ck_sel = 1; + phy_base->phy_indbg_ctrl.bits.txdata_debugmode = 0; + + // phy_enable + ret = sun20i_d1_hdmi_phy_enable(phy_base); + if (ret) + return ret; + + phy_base->phy_ctl0.bits.sda_en = 1; + phy_base->phy_ctl0.bits.scl_en = 1; + phy_base->phy_ctl0.bits.hpd_en = 1; + phy_base->phy_ctl0.bits.reg_den = 0xF; + phy_base->pll_ctl0.bits.envbs = 1; return 0; } @@ -720,6 +875,7 @@ static int sun8i_hdmi_phy_probe(struct p return dev_err_probe(dev, PTR_ERR(regs), "Couldn't map the HDMI PHY registers\n"); + phy->base = regs; phy->regs = devm_regmap_init_mmio(dev, regs, &sun8i_hdmi_phy_regmap_config); if (IS_ERR(phy->regs))