drm/i915: Address broxton phy registers based on phy and channel number

The port registers related to the phys in broxton map to different
channels and specific phys. Make that mapping explicit.

v2: Pass enum dpio_phy to macros instead of mmio base. (Imre)

v3: Fix typo in macros. (Imre)

v4: Also change variables from u32 to enum dpio_phy. (Imre)
    Remove leftovers from previous version. (Imre)

v5: Actually git add the changes.
Signed-off-by: default avatarAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476863940-6019-1-git-send-email-ander.conselvan.de.oliveira@intel.com
parent e7583f7b
...@@ -3761,6 +3761,8 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg); ...@@ -3761,6 +3761,8 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
/* intel_dpio_phy.c */ /* intel_dpio_phy.c */
void bxt_port_to_phy_channel(enum port port,
enum dpio_phy *phy, enum dpio_channel *ch);
void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
enum port port, u32 margin, u32 scale, enum port port, u32 margin, u32 scale,
u32 enable, u32 deemphasis); u32 enable, u32 deemphasis);
......
...@@ -1186,7 +1186,19 @@ enum skl_disp_power_wells { ...@@ -1186,7 +1186,19 @@ enum skl_disp_power_wells {
#define DPIO_UPAR_SHIFT 30 #define DPIO_UPAR_SHIFT 30
/* BXT PHY registers */ /* BXT PHY registers */
#define _BXT_PHY(phy, a, b) _MMIO_PIPE((phy), (a), (b)) #define _BXT_PHY0_BASE 0x6C000
#define _BXT_PHY1_BASE 0x162000
#define BXT_PHY_BASE(phy) _PIPE((phy), _BXT_PHY0_BASE, \
_BXT_PHY1_BASE)
#define _BXT_PHY(phy, reg) \
_MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg))
#define _BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \
(BXT_PHY_BASE(phy) + _PIPE((ch), (reg_ch0) - _BXT_PHY0_BASE, \
(reg_ch1) - _BXT_PHY0_BASE))
#define _MMIO_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \
_MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1))
#define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090) #define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090)
#define GT_DISPLAY_POWER_ON(phy) (1 << (phy)) #define GT_DISPLAY_POWER_ON(phy) (1 << (phy))
...@@ -1203,7 +1215,7 @@ enum skl_disp_power_wells { ...@@ -1203,7 +1215,7 @@ enum skl_disp_power_wells {
#define _PHY_CTL_FAMILY_EDP 0x64C80 #define _PHY_CTL_FAMILY_EDP 0x64C80
#define _PHY_CTL_FAMILY_DDI 0x64C90 #define _PHY_CTL_FAMILY_DDI 0x64C90
#define COMMON_RESET_DIS (1 << 31) #define COMMON_RESET_DIS (1 << 31)
#define BXT_PHY_CTL_FAMILY(phy) _BXT_PHY((phy), _PHY_CTL_FAMILY_DDI, \ #define BXT_PHY_CTL_FAMILY(phy) _MMIO_PIPE((phy), _PHY_CTL_FAMILY_DDI, \
_PHY_CTL_FAMILY_EDP) _PHY_CTL_FAMILY_EDP)
/* BXT PHY PLL registers */ /* BXT PHY PLL registers */
...@@ -1224,7 +1236,7 @@ enum skl_disp_power_wells { ...@@ -1224,7 +1236,7 @@ enum skl_disp_power_wells {
#define PORT_PLL_P2_SHIFT 8 #define PORT_PLL_P2_SHIFT 8
#define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT) #define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT)
#define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT) #define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT)
#define BXT_PORT_PLL_EBB_0(port) _MMIO_PORT3(port, _PORT_PLL_EBB_0_A, \ #define BXT_PORT_PLL_EBB_0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PLL_EBB_0_B, \ _PORT_PLL_EBB_0_B, \
_PORT_PLL_EBB_0_C) _PORT_PLL_EBB_0_C)
...@@ -1233,7 +1245,7 @@ enum skl_disp_power_wells { ...@@ -1233,7 +1245,7 @@ enum skl_disp_power_wells {
#define _PORT_PLL_EBB_4_C 0x6C344 #define _PORT_PLL_EBB_4_C 0x6C344
#define PORT_PLL_10BIT_CLK_ENABLE (1 << 13) #define PORT_PLL_10BIT_CLK_ENABLE (1 << 13)
#define PORT_PLL_RECALIBRATE (1 << 14) #define PORT_PLL_RECALIBRATE (1 << 14)
#define BXT_PORT_PLL_EBB_4(port) _MMIO_PORT3(port, _PORT_PLL_EBB_4_A, \ #define BXT_PORT_PLL_EBB_4(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PLL_EBB_4_B, \ _PORT_PLL_EBB_4_B, \
_PORT_PLL_EBB_4_C) _PORT_PLL_EBB_4_C)
...@@ -1266,62 +1278,56 @@ enum skl_disp_power_wells { ...@@ -1266,62 +1278,56 @@ enum skl_disp_power_wells {
#define PORT_PLL_DCO_AMP_DEFAULT 15 #define PORT_PLL_DCO_AMP_DEFAULT 15
#define PORT_PLL_DCO_AMP_MASK 0x3c00 #define PORT_PLL_DCO_AMP_MASK 0x3c00
#define PORT_PLL_DCO_AMP(x) ((x)<<10) #define PORT_PLL_DCO_AMP(x) ((x)<<10)
#define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \ #define _PORT_PLL_BASE(phy, ch) _BXT_PHY_CH(phy, ch, \
_PORT_PLL_0_B, \ _PORT_PLL_0_B, \
_PORT_PLL_0_C) _PORT_PLL_0_C)
#define BXT_PORT_PLL(port, idx) _MMIO(_PORT_PLL_BASE(port) + (idx) * 4) #define BXT_PORT_PLL(phy, ch, idx) _MMIO(_PORT_PLL_BASE(phy, ch) + \
(idx) * 4)
/* BXT PHY common lane registers */ /* BXT PHY common lane registers */
#define _PORT_CL1CM_DW0_A 0x162000 #define _PORT_CL1CM_DW0_A 0x162000
#define _PORT_CL1CM_DW0_BC 0x6C000 #define _PORT_CL1CM_DW0_BC 0x6C000
#define PHY_POWER_GOOD (1 << 16) #define PHY_POWER_GOOD (1 << 16)
#define PHY_RESERVED (1 << 7) #define PHY_RESERVED (1 << 7)
#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \ #define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC)
_PORT_CL1CM_DW0_A)
#define _PORT_CL1CM_DW9_A 0x162024 #define _PORT_CL1CM_DW9_A 0x162024
#define _PORT_CL1CM_DW9_BC 0x6C024 #define _PORT_CL1CM_DW9_BC 0x6C024
#define IREF0RC_OFFSET_SHIFT 8 #define IREF0RC_OFFSET_SHIFT 8
#define IREF0RC_OFFSET_MASK (0xFF << IREF0RC_OFFSET_SHIFT) #define IREF0RC_OFFSET_MASK (0xFF << IREF0RC_OFFSET_SHIFT)
#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC, \ #define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC)
_PORT_CL1CM_DW9_A)
#define _PORT_CL1CM_DW10_A 0x162028 #define _PORT_CL1CM_DW10_A 0x162028
#define _PORT_CL1CM_DW10_BC 0x6C028 #define _PORT_CL1CM_DW10_BC 0x6C028
#define IREF1RC_OFFSET_SHIFT 8 #define IREF1RC_OFFSET_SHIFT 8
#define IREF1RC_OFFSET_MASK (0xFF << IREF1RC_OFFSET_SHIFT) #define IREF1RC_OFFSET_MASK (0xFF << IREF1RC_OFFSET_SHIFT)
#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC, \ #define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC)
_PORT_CL1CM_DW10_A)
#define _PORT_CL1CM_DW28_A 0x162070 #define _PORT_CL1CM_DW28_A 0x162070
#define _PORT_CL1CM_DW28_BC 0x6C070 #define _PORT_CL1CM_DW28_BC 0x6C070
#define OCL1_POWER_DOWN_EN (1 << 23) #define OCL1_POWER_DOWN_EN (1 << 23)
#define DW28_OLDO_DYN_PWR_DOWN_EN (1 << 22) #define DW28_OLDO_DYN_PWR_DOWN_EN (1 << 22)
#define SUS_CLK_CONFIG 0x3 #define SUS_CLK_CONFIG 0x3
#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC, \ #define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC)
_PORT_CL1CM_DW28_A)
#define _PORT_CL1CM_DW30_A 0x162078 #define _PORT_CL1CM_DW30_A 0x162078
#define _PORT_CL1CM_DW30_BC 0x6C078 #define _PORT_CL1CM_DW30_BC 0x6C078
#define OCL2_LDOFUSE_PWR_DIS (1 << 6) #define OCL2_LDOFUSE_PWR_DIS (1 << 6)
#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \ #define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC)
_PORT_CL1CM_DW30_A)
/* The spec defines this only for BXT PHY0, but lets assume that this /* The spec defines this only for BXT PHY0, but lets assume that this
* would exist for PHY1 too if it had a second channel. * would exist for PHY1 too if it had a second channel.
*/ */
#define _PORT_CL2CM_DW6_A 0x162358 #define _PORT_CL2CM_DW6_A 0x162358
#define _PORT_CL2CM_DW6_BC 0x6C358 #define _PORT_CL2CM_DW6_BC 0x6C358
#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC, \ #define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC)
_PORT_CL2CM_DW6_A)
#define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28) #define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28)
/* BXT PHY Ref registers */ /* BXT PHY Ref registers */
#define _PORT_REF_DW3_A 0x16218C #define _PORT_REF_DW3_A 0x16218C
#define _PORT_REF_DW3_BC 0x6C18C #define _PORT_REF_DW3_BC 0x6C18C
#define GRC_DONE (1 << 22) #define GRC_DONE (1 << 22)
#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC, \ #define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC)
_PORT_REF_DW3_A)
#define _PORT_REF_DW6_A 0x162198 #define _PORT_REF_DW6_A 0x162198
#define _PORT_REF_DW6_BC 0x6C198 #define _PORT_REF_DW6_BC 0x6C198
...@@ -1332,15 +1338,13 @@ enum skl_disp_power_wells { ...@@ -1332,15 +1338,13 @@ enum skl_disp_power_wells {
#define GRC_CODE_SLOW_SHIFT 8 #define GRC_CODE_SLOW_SHIFT 8
#define GRC_CODE_SLOW_MASK (0xFF << GRC_CODE_SLOW_SHIFT) #define GRC_CODE_SLOW_MASK (0xFF << GRC_CODE_SLOW_SHIFT)
#define GRC_CODE_NOM_MASK 0xFF #define GRC_CODE_NOM_MASK 0xFF
#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC, \ #define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC)
_PORT_REF_DW6_A)
#define _PORT_REF_DW8_A 0x1621A0 #define _PORT_REF_DW8_A 0x1621A0
#define _PORT_REF_DW8_BC 0x6C1A0 #define _PORT_REF_DW8_BC 0x6C1A0
#define GRC_DIS (1 << 15) #define GRC_DIS (1 << 15)
#define GRC_RDY_OVRD (1 << 1) #define GRC_RDY_OVRD (1 << 1)
#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC, \ #define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC)
_PORT_REF_DW8_A)
/* BXT PHY PCS registers */ /* BXT PHY PCS registers */
#define _PORT_PCS_DW10_LN01_A 0x162428 #define _PORT_PCS_DW10_LN01_A 0x162428
...@@ -1349,12 +1353,13 @@ enum skl_disp_power_wells { ...@@ -1349,12 +1353,13 @@ enum skl_disp_power_wells {
#define _PORT_PCS_DW10_GRP_A 0x162C28 #define _PORT_PCS_DW10_GRP_A 0x162C28
#define _PORT_PCS_DW10_GRP_B 0x6CC28 #define _PORT_PCS_DW10_GRP_B 0x6CC28
#define _PORT_PCS_DW10_GRP_C 0x6CE28 #define _PORT_PCS_DW10_GRP_C 0x6CE28
#define BXT_PORT_PCS_DW10_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW10_LN01_A, \ #define BXT_PORT_PCS_DW10_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PCS_DW10_LN01_B, \ _PORT_PCS_DW10_LN01_B, \
_PORT_PCS_DW10_LN01_C) _PORT_PCS_DW10_LN01_C)
#define BXT_PORT_PCS_DW10_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW10_GRP_A, \ #define BXT_PORT_PCS_DW10_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PCS_DW10_GRP_B, \ _PORT_PCS_DW10_GRP_B, \
_PORT_PCS_DW10_GRP_C) _PORT_PCS_DW10_GRP_C)
#define TX2_SWING_CALC_INIT (1 << 31) #define TX2_SWING_CALC_INIT (1 << 31)
#define TX1_SWING_CALC_INIT (1 << 30) #define TX1_SWING_CALC_INIT (1 << 30)
...@@ -1369,13 +1374,13 @@ enum skl_disp_power_wells { ...@@ -1369,13 +1374,13 @@ enum skl_disp_power_wells {
#define _PORT_PCS_DW12_GRP_C 0x6CE30 #define _PORT_PCS_DW12_GRP_C 0x6CE30
#define LANESTAGGER_STRAP_OVRD (1 << 6) #define LANESTAGGER_STRAP_OVRD (1 << 6)
#define LANE_STAGGER_MASK 0x1F #define LANE_STAGGER_MASK 0x1F
#define BXT_PORT_PCS_DW12_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN01_A, \ #define BXT_PORT_PCS_DW12_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PCS_DW12_LN01_B, \ _PORT_PCS_DW12_LN01_B, \
_PORT_PCS_DW12_LN01_C) _PORT_PCS_DW12_LN01_C)
#define BXT_PORT_PCS_DW12_LN23(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN23_A, \ #define BXT_PORT_PCS_DW12_LN23(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PCS_DW12_LN23_B, \ _PORT_PCS_DW12_LN23_B, \
_PORT_PCS_DW12_LN23_C) _PORT_PCS_DW12_LN23_C)
#define BXT_PORT_PCS_DW12_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW12_GRP_A, \ #define BXT_PORT_PCS_DW12_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_PCS_DW12_GRP_B, \ _PORT_PCS_DW12_GRP_B, \
_PORT_PCS_DW12_GRP_C) _PORT_PCS_DW12_GRP_C)
...@@ -1389,12 +1394,12 @@ enum skl_disp_power_wells { ...@@ -1389,12 +1394,12 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW2_GRP_A 0x162D08 #define _PORT_TX_DW2_GRP_A 0x162D08
#define _PORT_TX_DW2_GRP_B 0x6CD08 #define _PORT_TX_DW2_GRP_B 0x6CD08
#define _PORT_TX_DW2_GRP_C 0x6CF08 #define _PORT_TX_DW2_GRP_C 0x6CF08
#define BXT_PORT_TX_DW2_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW2_GRP_A, \ #define BXT_PORT_TX_DW2_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_TX_DW2_GRP_B, \
_PORT_TX_DW2_GRP_C)
#define BXT_PORT_TX_DW2_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW2_LN0_A, \
_PORT_TX_DW2_LN0_B, \ _PORT_TX_DW2_LN0_B, \
_PORT_TX_DW2_LN0_C) _PORT_TX_DW2_LN0_C)
#define BXT_PORT_TX_DW2_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_TX_DW2_GRP_B, \
_PORT_TX_DW2_GRP_C)
#define MARGIN_000_SHIFT 16 #define MARGIN_000_SHIFT 16
#define MARGIN_000 (0xFF << MARGIN_000_SHIFT) #define MARGIN_000 (0xFF << MARGIN_000_SHIFT)
#define UNIQ_TRANS_SCALE_SHIFT 8 #define UNIQ_TRANS_SCALE_SHIFT 8
...@@ -1406,12 +1411,12 @@ enum skl_disp_power_wells { ...@@ -1406,12 +1411,12 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW3_GRP_A 0x162D0C #define _PORT_TX_DW3_GRP_A 0x162D0C
#define _PORT_TX_DW3_GRP_B 0x6CD0C #define _PORT_TX_DW3_GRP_B 0x6CD0C
#define _PORT_TX_DW3_GRP_C 0x6CF0C #define _PORT_TX_DW3_GRP_C 0x6CF0C
#define BXT_PORT_TX_DW3_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW3_GRP_A, \ #define BXT_PORT_TX_DW3_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_TX_DW3_GRP_B, \
_PORT_TX_DW3_GRP_C)
#define BXT_PORT_TX_DW3_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW3_LN0_A, \
_PORT_TX_DW3_LN0_B, \ _PORT_TX_DW3_LN0_B, \
_PORT_TX_DW3_LN0_C) _PORT_TX_DW3_LN0_C)
#define BXT_PORT_TX_DW3_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_TX_DW3_GRP_B, \
_PORT_TX_DW3_GRP_C)
#define SCALE_DCOMP_METHOD (1 << 26) #define SCALE_DCOMP_METHOD (1 << 26)
#define UNIQUE_TRANGE_EN_METHOD (1 << 27) #define UNIQUE_TRANGE_EN_METHOD (1 << 27)
...@@ -1421,10 +1426,10 @@ enum skl_disp_power_wells { ...@@ -1421,10 +1426,10 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW4_GRP_A 0x162D10 #define _PORT_TX_DW4_GRP_A 0x162D10
#define _PORT_TX_DW4_GRP_B 0x6CD10 #define _PORT_TX_DW4_GRP_B 0x6CD10
#define _PORT_TX_DW4_GRP_C 0x6CF10 #define _PORT_TX_DW4_GRP_C 0x6CF10
#define BXT_PORT_TX_DW4_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW4_LN0_A, \ #define BXT_PORT_TX_DW4_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_TX_DW4_LN0_B, \ _PORT_TX_DW4_LN0_B, \
_PORT_TX_DW4_LN0_C) _PORT_TX_DW4_LN0_C)
#define BXT_PORT_TX_DW4_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW4_GRP_A, \ #define BXT_PORT_TX_DW4_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
_PORT_TX_DW4_GRP_B, \ _PORT_TX_DW4_GRP_B, \
_PORT_TX_DW4_GRP_C) _PORT_TX_DW4_GRP_C)
#define DEEMPH_SHIFT 24 #define DEEMPH_SHIFT 24
...@@ -1435,8 +1440,8 @@ enum skl_disp_power_wells { ...@@ -1435,8 +1440,8 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW14_LN0_C 0x6C938 #define _PORT_TX_DW14_LN0_C 0x6C938
#define LATENCY_OPTIM_SHIFT 30 #define LATENCY_OPTIM_SHIFT 30
#define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT) #define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT)
#define BXT_PORT_TX_DW14_LN(port, lane) _MMIO(_PORT3((port), _PORT_TX_DW14_LN0_A, \ #define BXT_PORT_TX_DW14_LN(phy, ch, lane) \
_PORT_TX_DW14_LN0_B, \ _MMIO(_BXT_PHY_CH(phy, ch, _PORT_TX_DW14_LN0_B, \
_PORT_TX_DW14_LN0_C) + \ _PORT_TX_DW14_LN0_C) + \
_BXT_LANE_OFFSET(lane)) _BXT_LANE_OFFSET(lane))
......
...@@ -167,26 +167,58 @@ static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info) ...@@ -167,26 +167,58 @@ static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
BIT(phy_info->channel[DPIO_CH0].port); BIT(phy_info->channel[DPIO_CH0].port);
} }
void bxt_port_to_phy_channel(enum port port,
enum dpio_phy *phy, enum dpio_channel *ch)
{
const struct bxt_ddi_phy_info *phy_info;
int i;
for (i = 0; i < ARRAY_SIZE(bxt_ddi_phy_info); i++) {
phy_info = &bxt_ddi_phy_info[i];
if (port == phy_info->channel[DPIO_CH0].port) {
*phy = i;
*ch = DPIO_CH0;
return;
}
if (phy_info->dual_channel &&
port == phy_info->channel[DPIO_CH1].port) {
*phy = i;
*ch = DPIO_CH1;
return;
}
}
WARN(1, "PHY not found for PORT %c", port_name(port));
*phy = DPIO_PHY0;
*ch = DPIO_CH0;
}
void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
enum port port, u32 margin, u32 scale, enum port port, u32 margin, u32 scale,
u32 enable, u32 deemphasis) u32 enable, u32 deemphasis)
{ {
u32 val; u32 val;
enum dpio_phy phy;
enum dpio_channel ch;
bxt_port_to_phy_channel(port, &phy, &ch);
/* /*
* While we write to the group register to program all lanes at once we * While we write to the group register to program all lanes at once we
* can read only lane registers and we pick lanes 0/1 for that. * can read only lane registers and we pick lanes 0/1 for that.
*/ */
val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch));
val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val);
val = I915_READ(BXT_PORT_TX_DW2_LN0(port)); val = I915_READ(BXT_PORT_TX_DW2_LN0(phy, ch));
val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE);
val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT; val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT;
I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val); I915_WRITE(BXT_PORT_TX_DW2_GRP(phy, ch), val);
val = I915_READ(BXT_PORT_TX_DW3_LN0(port)); val = I915_READ(BXT_PORT_TX_DW3_LN0(phy, ch));
val &= ~SCALE_DCOMP_METHOD; val &= ~SCALE_DCOMP_METHOD;
if (enable) if (enable)
val |= SCALE_DCOMP_METHOD; val |= SCALE_DCOMP_METHOD;
...@@ -194,16 +226,16 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, ...@@ -194,16 +226,16 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD))
DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set"); DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set");
I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val); I915_WRITE(BXT_PORT_TX_DW3_GRP(phy, ch), val);
val = I915_READ(BXT_PORT_TX_DW4_LN0(port)); val = I915_READ(BXT_PORT_TX_DW4_LN0(phy, ch));
val &= ~DE_EMPHASIS; val &= ~DE_EMPHASIS;
val |= deemphasis << DEEMPH_SHIFT; val |= deemphasis << DEEMPH_SHIFT;
I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val); I915_WRITE(BXT_PORT_TX_DW4_GRP(phy, ch), val);
val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch));
val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT;
I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val);
} }
bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
...@@ -525,10 +557,14 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, ...@@ -525,10 +557,14 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
enum port port = dport->port; enum port port = dport->port;
enum dpio_phy phy;
enum dpio_channel ch;
int lane; int lane;
bxt_port_to_phy_channel(port, &phy, &ch);
for (lane = 0; lane < 4; lane++) { for (lane = 0; lane < 4; lane++) {
u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
/* /*
* Note that on CHV this flag is called UPAR, but has * Note that on CHV this flag is called UPAR, but has
...@@ -538,7 +574,7 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, ...@@ -538,7 +574,7 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
if (lane_lat_optim_mask & BIT(lane)) if (lane_lat_optim_mask & BIT(lane))
val |= LATENCY_OPTIM; val |= LATENCY_OPTIM;
I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); I915_WRITE(BXT_PORT_TX_DW14_LN(phy, ch, lane), val);
} }
} }
...@@ -548,12 +584,16 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) ...@@ -548,12 +584,16 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
enum port port = dport->port; enum port port = dport->port;
enum dpio_phy phy;
enum dpio_channel ch;
int lane; int lane;
uint8_t mask; uint8_t mask;
bxt_port_to_phy_channel(port, &phy, &ch);
mask = 0; mask = 0;
for (lane = 0; lane < 4; lane++) { for (lane = 0; lane < 4; lane++) {
u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
if (val & LATENCY_OPTIM) if (val & LATENCY_OPTIM)
mask |= BIT(lane); mask |= BIT(lane);
......
...@@ -1371,6 +1371,10 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, ...@@ -1371,6 +1371,10 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
{ {
uint32_t temp; uint32_t temp;
enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
enum dpio_phy phy;
enum dpio_channel ch;
bxt_port_to_phy_channel(port, &phy, &ch);
/* Non-SSC reference */ /* Non-SSC reference */
temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
...@@ -1378,72 +1382,72 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, ...@@ -1378,72 +1382,72 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
/* Disable 10 bit clock */ /* Disable 10 bit clock */
temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
temp &= ~PORT_PLL_10BIT_CLK_ENABLE; temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
/* Write P1 & P2 */ /* Write P1 & P2 */
temp = I915_READ(BXT_PORT_PLL_EBB_0(port)); temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK); temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
temp |= pll->config.hw_state.ebb0; temp |= pll->config.hw_state.ebb0;
I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp); I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
/* Write M2 integer */ /* Write M2 integer */
temp = I915_READ(BXT_PORT_PLL(port, 0)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
temp &= ~PORT_PLL_M2_MASK; temp &= ~PORT_PLL_M2_MASK;
temp |= pll->config.hw_state.pll0; temp |= pll->config.hw_state.pll0;
I915_WRITE(BXT_PORT_PLL(port, 0), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
/* Write N */ /* Write N */
temp = I915_READ(BXT_PORT_PLL(port, 1)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
temp &= ~PORT_PLL_N_MASK; temp &= ~PORT_PLL_N_MASK;
temp |= pll->config.hw_state.pll1; temp |= pll->config.hw_state.pll1;
I915_WRITE(BXT_PORT_PLL(port, 1), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
/* Write M2 fraction */ /* Write M2 fraction */
temp = I915_READ(BXT_PORT_PLL(port, 2)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
temp &= ~PORT_PLL_M2_FRAC_MASK; temp &= ~PORT_PLL_M2_FRAC_MASK;
temp |= pll->config.hw_state.pll2; temp |= pll->config.hw_state.pll2;
I915_WRITE(BXT_PORT_PLL(port, 2), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
/* Write M2 fraction enable */ /* Write M2 fraction enable */
temp = I915_READ(BXT_PORT_PLL(port, 3)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
temp &= ~PORT_PLL_M2_FRAC_ENABLE; temp &= ~PORT_PLL_M2_FRAC_ENABLE;
temp |= pll->config.hw_state.pll3; temp |= pll->config.hw_state.pll3;
I915_WRITE(BXT_PORT_PLL(port, 3), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
/* Write coeff */ /* Write coeff */
temp = I915_READ(BXT_PORT_PLL(port, 6)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
temp &= ~PORT_PLL_PROP_COEFF_MASK; temp &= ~PORT_PLL_PROP_COEFF_MASK;
temp &= ~PORT_PLL_INT_COEFF_MASK; temp &= ~PORT_PLL_INT_COEFF_MASK;
temp &= ~PORT_PLL_GAIN_CTL_MASK; temp &= ~PORT_PLL_GAIN_CTL_MASK;
temp |= pll->config.hw_state.pll6; temp |= pll->config.hw_state.pll6;
I915_WRITE(BXT_PORT_PLL(port, 6), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
/* Write calibration val */ /* Write calibration val */
temp = I915_READ(BXT_PORT_PLL(port, 8)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
temp &= ~PORT_PLL_TARGET_CNT_MASK; temp &= ~PORT_PLL_TARGET_CNT_MASK;
temp |= pll->config.hw_state.pll8; temp |= pll->config.hw_state.pll8;
I915_WRITE(BXT_PORT_PLL(port, 8), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
temp = I915_READ(BXT_PORT_PLL(port, 9)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK; temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
temp |= pll->config.hw_state.pll9; temp |= pll->config.hw_state.pll9;
I915_WRITE(BXT_PORT_PLL(port, 9), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
temp = I915_READ(BXT_PORT_PLL(port, 10)); temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
temp &= ~PORT_PLL_DCO_AMP_MASK; temp &= ~PORT_PLL_DCO_AMP_MASK;
temp |= pll->config.hw_state.pll10; temp |= pll->config.hw_state.pll10;
I915_WRITE(BXT_PORT_PLL(port, 10), temp); I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
/* Recalibrate with new settings */ /* Recalibrate with new settings */
temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
temp |= PORT_PLL_RECALIBRATE; temp |= PORT_PLL_RECALIBRATE;
I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
temp &= ~PORT_PLL_10BIT_CLK_ENABLE; temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
temp |= pll->config.hw_state.ebb4; temp |= pll->config.hw_state.ebb4;
I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
/* Enable PLL */ /* Enable PLL */
temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
...@@ -1459,11 +1463,11 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, ...@@ -1459,11 +1463,11 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
* While we write to the group register to program all lanes at once we * While we write to the group register to program all lanes at once we
* can read only lane registers and we pick lanes 0/1 for that. * can read only lane registers and we pick lanes 0/1 for that.
*/ */
temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
temp &= ~LANE_STAGGER_MASK; temp &= ~LANE_STAGGER_MASK;
temp &= ~LANESTAGGER_STRAP_OVRD; temp &= ~LANESTAGGER_STRAP_OVRD;
temp |= pll->config.hw_state.pcsdw12; temp |= pll->config.hw_state.pcsdw12;
I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp); I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
} }
static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
...@@ -1485,6 +1489,10 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, ...@@ -1485,6 +1489,10 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
uint32_t val; uint32_t val;
bool ret; bool ret;
enum dpio_phy phy;
enum dpio_channel ch;
bxt_port_to_phy_channel(port, &phy, &ch);
if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
return false; return false;
...@@ -1495,36 +1503,36 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, ...@@ -1495,36 +1503,36 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
if (!(val & PORT_PLL_ENABLE)) if (!(val & PORT_PLL_ENABLE))
goto out; goto out;
hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port)); hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
hw_state->pll0 &= PORT_PLL_M2_MASK; hw_state->pll0 &= PORT_PLL_M2_MASK;
hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
hw_state->pll1 &= PORT_PLL_N_MASK; hw_state->pll1 &= PORT_PLL_N_MASK;
hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK; hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE; hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK | hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
PORT_PLL_INT_COEFF_MASK | PORT_PLL_INT_COEFF_MASK |
PORT_PLL_GAIN_CTL_MASK; PORT_PLL_GAIN_CTL_MASK;
hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK; hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9)); hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H | hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
PORT_PLL_DCO_AMP_MASK; PORT_PLL_DCO_AMP_MASK;
...@@ -1533,11 +1541,11 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, ...@@ -1533,11 +1541,11 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
* can read only lane registers. We configure all lanes the same way, so * can read only lane registers. We configure all lanes the same way, so
* here just read out lanes 0/1 and output a note if lanes 2/3 differ. * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
*/ */
hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12) if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
hw_state->pcsdw12, hw_state->pcsdw12,
I915_READ(BXT_PORT_PCS_DW12_LN23(port))); I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
ret = true; ret = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment