Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2015 Broadcom
0004  * Copyright (c) 2014 The Linux Foundation. All rights reserved.
0005  * Copyright (C) 2013 Red Hat
0006  * Author: Rob Clark <robdclark@gmail.com>
0007  */
0008 
0009 #include "vc4_hdmi.h"
0010 #include "vc4_regs.h"
0011 #include "vc4_hdmi_regs.h"
0012 
0013 #define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB    BIT(5)
0014 #define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB BIT(4)
0015 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET   BIT(3)
0016 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET    BIT(2)
0017 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET    BIT(1)
0018 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET    BIT(0)
0019 
0020 #define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN  BIT(4)
0021 
0022 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT 29
0023 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK  VC4_MASK(31, 29)
0024 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT    24
0025 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK VC4_MASK(28, 24)
0026 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT 21
0027 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK  VC4_MASK(23, 21)
0028 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT    16
0029 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK VC4_MASK(20, 16)
0030 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT 13
0031 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK  VC4_MASK(15, 13)
0032 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT    8
0033 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK VC4_MASK(12, 8)
0034 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT    5
0035 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK VC4_MASK(7, 5)
0036 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT   0
0037 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK    VC4_MASK(4, 0)
0038 
0039 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT   15
0040 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK    VC4_MASK(19, 15)
0041 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT   10
0042 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK    VC4_MASK(14, 10)
0043 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT   5
0044 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK    VC4_MASK(9, 5)
0045 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT      0
0046 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK       VC4_MASK(4, 0)
0047 
0048 #define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT        16
0049 #define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK     VC4_MASK(19, 16)
0050 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT   12
0051 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK    VC4_MASK(15, 12)
0052 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT   8
0053 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK    VC4_MASK(11, 8)
0054 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT   4
0055 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK    VC4_MASK(7, 4)
0056 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT  0
0057 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK   VC4_MASK(3, 0)
0058 
0059 #define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT          17
0060 #define VC4_HDMI_TX_PHY_CTL_3_RP_MASK           VC4_MASK(19, 17)
0061 #define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT          12
0062 #define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK           VC4_MASK(16, 12)
0063 #define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT         10
0064 #define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK          VC4_MASK(11, 10)
0065 #define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT          8
0066 #define VC4_HDMI_TX_PHY_CTL_3_CP_MASK           VC4_MASK(9, 8)
0067 #define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT          6
0068 #define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK           VC4_MASK(7, 6)
0069 #define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT         0
0070 #define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK          VC4_MASK(5, 0)
0071 
0072 #define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE       BIT(13)
0073 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN       BIT(12)
0074 #define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW    BIT(11)
0075 #define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH   BIT(10)
0076 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT     9
0077 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK      VC4_MASK(9, 9)
0078 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2       BIT(8)
0079 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2     BIT(7)
0080 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN       BIT(6)
0081 #define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK       BIT(5)
0082 
0083 #define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT         16
0084 #define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK          VC4_MASK(27, 16)
0085 #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT  14
0086 #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK   VC4_MASK(15, 14)
0087 #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE       BIT(13)
0088 #define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT        11
0089 #define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK     VC4_MASK(12, 11)
0090 
0091 #define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT       8
0092 #define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK        VC4_MASK(15, 8)
0093 
0094 #define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT      0
0095 #define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK       VC4_MASK(3, 0)
0096 
0097 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK  VC4_MASK(13, 12)
0098 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT 12
0099 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK   VC4_MASK(9, 8)
0100 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT  8
0101 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK   VC4_MASK(5, 4)
0102 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT  4
0103 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK   VC4_MASK(1, 0)
0104 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT  0
0105 
0106 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK     VC4_MASK(27, 0)
0107 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT    0
0108 
0109 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK     VC4_MASK(27, 0)
0110 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT    0
0111 
0112 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK  VC4_MASK(31, 16)
0113 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT 16
0114 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK    VC4_MASK(15, 0)
0115 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT   0
0116 
0117 #define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS      BIT(19)
0118 #define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR      BIT(17)
0119 #define VC4_HDMI_RM_CONTROL_FREE_RUN            BIT(4)
0120 
0121 #define VC4_HDMI_RM_OFFSET_ONLY             BIT(31)
0122 #define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT         0
0123 #define VC4_HDMI_RM_OFFSET_OFFSET_MASK          VC4_MASK(30, 0)
0124 
0125 #define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT          24
0126 #define VC4_HDMI_RM_FORMAT_SHIFT_MASK           VC4_MASK(25, 24)
0127 
0128 #define OSCILLATOR_FREQUENCY    54000000
0129 
0130 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
0131                struct vc4_hdmi_connector_state *conn_state)
0132 {
0133     unsigned long flags;
0134 
0135     /* PHY should be in reset, like
0136      * vc4_hdmi_encoder_disable() does.
0137      */
0138 
0139     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0140 
0141     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
0142     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
0143 
0144     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0145 }
0146 
0147 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
0148 {
0149     unsigned long flags;
0150 
0151     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0152     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
0153     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0154 }
0155 
0156 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
0157 {
0158     unsigned long flags;
0159 
0160     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0161     HDMI_WRITE(HDMI_TX_PHY_CTL_0,
0162            HDMI_READ(HDMI_TX_PHY_CTL_0) &
0163            ~VC4_HDMI_TX_PHY_RNG_PWRDN);
0164     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0165 }
0166 
0167 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
0168 {
0169     unsigned long flags;
0170 
0171     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0172     HDMI_WRITE(HDMI_TX_PHY_CTL_0,
0173            HDMI_READ(HDMI_TX_PHY_CTL_0) |
0174            VC4_HDMI_TX_PHY_RNG_PWRDN);
0175     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0176 }
0177 
0178 static unsigned long long
0179 phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
0180 {
0181     unsigned long long vco_freq = clock;
0182     unsigned int _vco_div = 0;
0183     unsigned int _vco_sel = 0;
0184 
0185     while (vco_freq < 3000000000ULL) {
0186         _vco_div++;
0187         vco_freq = clock * _vco_div * 10;
0188     }
0189 
0190     if (vco_freq > 4500000000ULL)
0191         _vco_sel = 1;
0192 
0193     *vco_sel = _vco_sel;
0194     *vco_div = _vco_div;
0195 
0196     return vco_freq;
0197 }
0198 
0199 static u8 phy_get_cp_current(unsigned long vco_freq)
0200 {
0201     if (vco_freq < 3700000000ULL)
0202         return 0x1c;
0203 
0204     return 0x18;
0205 }
0206 
0207 static u32 phy_get_rm_offset(unsigned long long vco_freq)
0208 {
0209     unsigned long long fref = OSCILLATOR_FREQUENCY;
0210     u64 offset = 0;
0211 
0212     /* RM offset is stored as 9.22 format */
0213     offset = vco_freq * 2;
0214     offset = offset << 22;
0215     do_div(offset, fref);
0216     offset >>= 2;
0217 
0218     return offset;
0219 }
0220 
0221 static u8 phy_get_vco_gain(unsigned long long vco_freq)
0222 {
0223     if (vco_freq < 3350000000ULL)
0224         return 0xf;
0225 
0226     if (vco_freq < 3700000000ULL)
0227         return 0xc;
0228 
0229     if (vco_freq < 4050000000ULL)
0230         return 0x6;
0231 
0232     if (vco_freq < 4800000000ULL)
0233         return 0x5;
0234 
0235     if (vco_freq < 5200000000ULL)
0236         return 0x7;
0237 
0238     return 0x2;
0239 }
0240 
0241 struct phy_lane_settings {
0242     struct {
0243         u8 preemphasis;
0244         u8 main_driver;
0245     } amplitude;
0246 
0247     u8 res_sel_data;
0248     u8 term_res_sel_data;
0249 };
0250 
0251 struct phy_settings {
0252     unsigned long long min_rate;
0253     unsigned long long max_rate;
0254     struct phy_lane_settings channel[3];
0255     struct phy_lane_settings clock;
0256 };
0257 
0258 static const struct phy_settings vc5_hdmi_phy_settings[] = {
0259     {
0260         0, 50000000,
0261         {
0262             {{0x0, 0x0A}, 0x12, 0x0},
0263             {{0x0, 0x0A}, 0x12, 0x0},
0264             {{0x0, 0x0A}, 0x12, 0x0}
0265         },
0266         {{0x0, 0x0A}, 0x18, 0x0},
0267     },
0268     {
0269         50000001, 75000000,
0270         {
0271             {{0x0, 0x09}, 0x12, 0x0},
0272             {{0x0, 0x09}, 0x12, 0x0},
0273             {{0x0, 0x09}, 0x12, 0x0}
0274         },
0275         {{0x0, 0x0C}, 0x18, 0x3},
0276     },
0277     {
0278         75000001,   165000000,
0279         {
0280             {{0x0, 0x09}, 0x12, 0x0},
0281             {{0x0, 0x09}, 0x12, 0x0},
0282             {{0x0, 0x09}, 0x12, 0x0}
0283         },
0284         {{0x0, 0x0C}, 0x18, 0x3},
0285     },
0286     {
0287         165000001,  250000000,
0288         {
0289             {{0x0, 0x0F}, 0x12, 0x1},
0290             {{0x0, 0x0F}, 0x12, 0x1},
0291             {{0x0, 0x0F}, 0x12, 0x1}
0292         },
0293         {{0x0, 0x0C}, 0x18, 0x3},
0294     },
0295     {
0296         250000001,  340000000,
0297         {
0298             {{0x2, 0x0D}, 0x12, 0x1},
0299             {{0x2, 0x0D}, 0x12, 0x1},
0300             {{0x2, 0x0D}, 0x12, 0x1}
0301         },
0302         {{0x0, 0x0C}, 0x18, 0xF},
0303     },
0304     {
0305         340000001,  450000000,
0306         {
0307             {{0x0, 0x1B}, 0x12, 0xF},
0308             {{0x0, 0x1B}, 0x12, 0xF},
0309             {{0x0, 0x1B}, 0x12, 0xF}
0310         },
0311         {{0x0, 0x0A}, 0x12, 0xF},
0312     },
0313     {
0314         450000001,  600000000,
0315         {
0316             {{0x0, 0x1C}, 0x12, 0xF},
0317             {{0x0, 0x1C}, 0x12, 0xF},
0318             {{0x0, 0x1C}, 0x12, 0xF}
0319         },
0320         {{0x0, 0x0B}, 0x13, 0xF},
0321     },
0322 };
0323 
0324 static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
0325 {
0326     unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
0327     unsigned int i;
0328 
0329     for (i = 0; i < count; i++) {
0330         const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
0331 
0332         if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
0333             return s;
0334     }
0335 
0336     /*
0337      * If the pixel clock exceeds our max setting, try the max
0338      * setting anyway.
0339      */
0340     return &vc5_hdmi_phy_settings[count - 1];
0341 }
0342 
0343 static const struct phy_lane_settings *
0344 phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
0345              unsigned long long tmds_rate)
0346 {
0347     const struct phy_settings *settings = phy_get_settings(tmds_rate);
0348 
0349     if (chan == PHY_LANE_CK)
0350         return &settings->clock;
0351 
0352     return &settings->channel[chan];
0353 }
0354 
0355 static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
0356 {
0357     lockdep_assert_held(&vc4_hdmi->hw_lock);
0358 
0359     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
0360     HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
0361 }
0362 
0363 void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
0364                struct vc4_hdmi_connector_state *conn_state)
0365 {
0366     const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
0367     const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
0368     unsigned long long pixel_freq = conn_state->tmds_char_rate;
0369     unsigned long long vco_freq;
0370     unsigned char word_sel;
0371     unsigned long flags;
0372     u8 vco_sel, vco_div;
0373 
0374     vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
0375 
0376     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0377 
0378     vc5_hdmi_reset_phy(vc4_hdmi);
0379 
0380     HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
0381            VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
0382 
0383     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
0384            HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
0385            ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
0386            ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
0387            ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
0388            ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
0389 
0390     HDMI_WRITE(HDMI_RM_CONTROL,
0391            HDMI_READ(HDMI_RM_CONTROL) |
0392            VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
0393            VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
0394            VC4_HDMI_RM_CONTROL_FREE_RUN);
0395 
0396     HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
0397            (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
0398             ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
0399            VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
0400 
0401     HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
0402            (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
0403             ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
0404            VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
0405 
0406     HDMI_WRITE(HDMI_RM_OFFSET,
0407            VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
0408                  VC4_HDMI_RM_OFFSET_OFFSET) |
0409            VC4_HDMI_RM_OFFSET_ONLY);
0410 
0411     HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
0412            VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
0413 
0414     HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
0415            VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
0416            VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
0417 
0418     HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
0419            VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
0420            VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
0421            VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
0422            VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
0423 
0424     HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
0425            HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
0426            VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
0427            VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
0428            VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
0429            VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
0430 
0431     HDMI_WRITE(HDMI_RM_FORMAT,
0432            HDMI_READ(HDMI_RM_FORMAT) |
0433            VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
0434 
0435     HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
0436            HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
0437            VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
0438 
0439     if (pixel_freq >= 340000000)
0440         word_sel = 3;
0441     else
0442         word_sel = 0;
0443     HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
0444 
0445     HDMI_WRITE(HDMI_TX_PHY_CTL_3,
0446            VC4_SET_FIELD(phy_get_cp_current(vco_freq),
0447                  VC4_HDMI_TX_PHY_CTL_3_ICP) |
0448            VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
0449            VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
0450            VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
0451            VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
0452            VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
0453 
0454     chan0_settings =
0455         phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
0456                      pixel_freq);
0457     chan1_settings =
0458         phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
0459                      pixel_freq);
0460     chan2_settings =
0461         phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
0462                      pixel_freq);
0463     clock_settings =
0464         phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
0465                      pixel_freq);
0466 
0467     HDMI_WRITE(HDMI_TX_PHY_CTL_0,
0468            VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
0469                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
0470            VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
0471                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
0472            VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
0473                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
0474            VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
0475                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
0476            VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
0477                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
0478            VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
0479                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
0480            VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
0481                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
0482            VC4_SET_FIELD(clock_settings->amplitude.main_driver,
0483                  VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
0484 
0485     HDMI_WRITE(HDMI_TX_PHY_CTL_1,
0486            HDMI_READ(HDMI_TX_PHY_CTL_1) |
0487            VC4_SET_FIELD(chan0_settings->res_sel_data,
0488                  VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
0489            VC4_SET_FIELD(chan1_settings->res_sel_data,
0490                  VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
0491            VC4_SET_FIELD(chan2_settings->res_sel_data,
0492                  VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
0493            VC4_SET_FIELD(clock_settings->res_sel_data,
0494                  VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
0495 
0496     HDMI_WRITE(HDMI_TX_PHY_CTL_2,
0497            VC4_SET_FIELD(chan0_settings->term_res_sel_data,
0498                  VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
0499            VC4_SET_FIELD(chan1_settings->term_res_sel_data,
0500                  VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
0501            VC4_SET_FIELD(chan2_settings->term_res_sel_data,
0502                  VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
0503            VC4_SET_FIELD(clock_settings->term_res_sel_data,
0504                  VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
0505            VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
0506                  VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
0507 
0508     HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
0509            VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
0510                  VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
0511            VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
0512                  VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
0513            VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
0514                  VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
0515            VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
0516                  VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
0517 
0518     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
0519            HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
0520            ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
0521              VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
0522 
0523     HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
0524            HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
0525            VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
0526            VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
0527 
0528     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0529 }
0530 
0531 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
0532 {
0533     unsigned long flags;
0534 
0535     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0536     vc5_hdmi_reset_phy(vc4_hdmi);
0537     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0538 }
0539 
0540 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
0541 {
0542     unsigned long flags;
0543 
0544     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0545     HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
0546            HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
0547            ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
0548     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0549 }
0550 
0551 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
0552 {
0553     unsigned long flags;
0554 
0555     spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
0556     HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
0557            HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
0558            VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
0559     spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
0560 }