diff options
Diffstat (limited to 'drivers/gpu/drm/imx/hdp/API_AFE_mcu1_dp.c')
-rw-r--r-- | drivers/gpu/drm/imx/hdp/API_AFE_mcu1_dp.c | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/hdp/API_AFE_mcu1_dp.c b/drivers/gpu/drm/imx/hdp/API_AFE_mcu1_dp.c new file mode 100644 index 000000000000..c22891423222 --- /dev/null +++ b/drivers/gpu/drm/imx/hdp/API_AFE_mcu1_dp.c @@ -0,0 +1,419 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017-2018 NXP + * + ****************************************************************************** + * + * API_AFE_mcu1_dp.c + * + ****************************************************************************** + */ + +#include <linux/delay.h> +#include "API_AFE_mcu1_dp.h" +#include "../../../../mxc/hdp/all.h" + +static void AFE_WriteReg(state_struct *state, ENUM_AFE_LINK_RATE link_rate, + unsigned int addr, + unsigned int val1_6, + unsigned int val2_1, + unsigned int val2_4, + unsigned int val2_7, + unsigned int val3_2, + unsigned int val4_3, + unsigned int val5_4) +{ + switch (link_rate) { + case AFE_LINK_RATE_1_6: + Afe_write(state, addr, val1_6); + break; + case AFE_LINK_RATE_2_1: + Afe_write(state, addr, val2_1); + break; + case AFE_LINK_RATE_2_4: + Afe_write(state, addr, val2_4); + break; + case AFE_LINK_RATE_2_7: + Afe_write(state, addr, val2_7); + break; + case AFE_LINK_RATE_3_2: + Afe_write(state, addr, val3_2); + break; + case AFE_LINK_RATE_4_3: + Afe_write(state, addr, val4_3); + break; + case AFE_LINK_RATE_5_4: + Afe_write(state, addr, val5_4); + break; + case AFE_LINK_RATE_8_1: /* Not used in MCU1 */ + default: + pr_err("Warning. Unsupported Link Rate!\n"); + break; + } +} + +static void phy_cfg_24mhz(state_struct *state, int num_lanes) +{ + int k; + + for (k = 0; k < num_lanes; k++) { + Afe_write(state, XCVR_DIAG_LANE_FCM_EN_MGN_TMR | (k << 9), 0x0090); + Afe_write(state, TX_RCVDET_EN_TMR | (k << 9), 0x0960); + Afe_write(state, TX_RCVDET_ST_TMR | (k << 9), 0x0030); + } +} + +/* Valid for 24 MHz only */ +static void phy_cfg_dp_pll0(state_struct *state, + int num_lanes, + ENUM_AFE_LINK_RATE link_rate) +{ + int k; + volatile u16 rdata; + + rdata = Afe_read(state, PHY_HDP_CLK_CTL); + rdata = rdata & 0x00FF; + + switch (link_rate) { + case AFE_LINK_RATE_1_6: + case AFE_LINK_RATE_2_1: + case AFE_LINK_RATE_2_4: + case AFE_LINK_RATE_2_7: + rdata = rdata | 0x2400; + break; + + case AFE_LINK_RATE_3_2: + case AFE_LINK_RATE_4_3: + case AFE_LINK_RATE_5_4: + rdata = rdata | 0x1200; + break; + + case AFE_LINK_RATE_8_1: /* nNot used in MCU1 */ + default: + pr_err("Warning. Unsupported Link Rate!\n"); + break; + } + + Afe_write(state, PHY_HDP_CLK_CTL, rdata); + rdata = Afe_read(state, CMN_DIAG_HSCLK_SEL); + rdata = rdata & 0xFFCC; + switch (link_rate) { + case AFE_LINK_RATE_1_6: + case AFE_LINK_RATE_2_1: + case AFE_LINK_RATE_2_4: + case AFE_LINK_RATE_2_7: + rdata = rdata | 0x0011; + break; + + case AFE_LINK_RATE_3_2: + case AFE_LINK_RATE_4_3: + case AFE_LINK_RATE_5_4: + rdata = rdata | 0x0000; + break; + + case AFE_LINK_RATE_8_1: /* Not used in MCU1 */ + default: + pr_err("Warning. Unsupported Link Rate!\n"); + break; + } + Afe_write(state, CMN_DIAG_HSCLK_SEL, rdata); + for (k = 0; k < num_lanes; k = k + 1) { + rdata = Afe_read(state, (XCVR_DIAG_HSCLK_SEL | (k << 9))); + rdata = rdata & 0xCFFF; + switch (link_rate) { + case AFE_LINK_RATE_1_6: + case AFE_LINK_RATE_2_1: + case AFE_LINK_RATE_2_4: + case AFE_LINK_RATE_2_7: + rdata = rdata | 0x1000; + break; + + case AFE_LINK_RATE_3_2: + case AFE_LINK_RATE_4_3: + case AFE_LINK_RATE_5_4: + rdata = rdata | 0x0000; + break; + + case AFE_LINK_RATE_8_1: /* Not used in MCU1 */ + default: + pr_err("Warning. Unsupported Link Rate!\n"); + break; + } + Afe_write(state, (XCVR_DIAG_HSCLK_SEL | (k << 9)), rdata); + } + Afe_write(state, CMN_PLL0_VCOCAL_INIT_TMR, 0x00F0); + Afe_write(state, CMN_PLL0_VCOCAL_ITER_TMR, 0x0018); + AFE_WriteReg(state, link_rate, CMN_PLL0_VCOCAL_START, 0x3061, 0x3092, 0x30B3, 0x30D0, 0x3061, 0x3092, 0x30D0); + AFE_WriteReg(state, link_rate, CMN_PLL0_INTDIV, 0x0086, 0x00B3, 0x00CA, 0x00E0, 0x0086, 0x00B3, 0x00E0); + AFE_WriteReg(state, link_rate, CMN_PLL0_FRACDIV, 0xF917, 0xF6C7, 0x75A1, 0xF479, 0xF917, 0xF6C7, 0xF479); + AFE_WriteReg(state, link_rate, CMN_PLL0_HIGH_THR, 0x0022, 0x002D, 0x0033, 0x0038, 0x0022, 0x002D, 0x0038); +#ifdef SSC_ON_INIT + AFE_WriteReg(state, link_rate, CMN_PLL0_SS_CTRL1, 0x0140, 0x01AB, 0x01E0, 0x0204, 0x0140, 0x01AB, 0x0204); + Afe_write(state, CMN_PLL0_SS_CTRL2, 0x7F03); +#endif + Afe_write(state, CMN_PLL0_DSM_DIAG, 0x0020); + AFE_WriteReg(state, link_rate, CMN_PLLSM0_USER_DEF_CTRL, 0x0000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x1000); + Afe_write(state, CMN_DIAG_PLL0_OVRD, 0x0000); + Afe_write(state, CMN_DIAG_PLL0_FBH_OVRD, 0x0000); + Afe_write(state, CMN_DIAG_PLL0_FBL_OVRD, 0x0000); + AFE_WriteReg(state, link_rate, CMN_DIAG_PLL0_V2I_TUNE, 0x0006, 0x0007, 0x0007, 0x0007, 0x0006, 0x0007, 0x0007); + AFE_WriteReg(state, link_rate, CMN_DIAG_PLL0_CP_TUNE, 0x0026, 0x0029, 0x0029, 0x0029, 0x0026, 0x0029, 0x0029); + Afe_write(state, CMN_DIAG_PLL0_LF_PROG, 0x0008); + Afe_write(state, CMN_DIAG_PLL0_PTATIS_TUNE1, 0x008C); + Afe_write(state, CMN_DIAG_PLL0_PTATIS_TUNE2, 0x002E); + for (k = 0; k < num_lanes; k = k + 1) { + rdata = Afe_read(state, (XCVR_DIAG_PLLDRC_CTRL | (k << 9))); + rdata = rdata & 0x8FFF; + switch (link_rate) { + case AFE_LINK_RATE_1_6: + case AFE_LINK_RATE_2_1: + case AFE_LINK_RATE_2_4: + case AFE_LINK_RATE_2_7: + rdata = rdata | 0x2000; + break; + + case AFE_LINK_RATE_3_2: + case AFE_LINK_RATE_4_3: + case AFE_LINK_RATE_5_4: + rdata = rdata | 0x1000; + break; + + case AFE_LINK_RATE_8_1: /* Not used in MCU1 */ + default: + pr_err("Warning. Unsupported Link Rate!\n"); + break; + } + Afe_write(state, (XCVR_DIAG_PLLDRC_CTRL | (k << 9)), rdata); + } +} + +static void phy_cfg_dp_ln(state_struct *state, int num_lanes) +{ + int k; + u16 rdata; + + for (k = 0; k < num_lanes; k = k + 1) { + Afe_write(state, (XCVR_PSM_RCTRL | (k << 9)), 0xBEFC); + if (state->edp == 0) { + Afe_write(state, (TX_PSC_A0 | (k << 9)), 0x6799); + Afe_write(state, (TX_PSC_A1 | (k << 9)), 0x6798); + Afe_write(state, (TX_PSC_A2 | (k << 9)), 0x0098); + Afe_write(state, (TX_PSC_A3 | (k << 9)), 0x0098); + } else { + Afe_write(state, (TX_PSC_A0 | (k << 9)), 0x279B); + Afe_write(state, (TX_PSC_A1 | (k << 9)), 0x2798); + Afe_write(state, (TX_PSC_A2 | (k << 9)), 0x0098); + Afe_write(state, (TX_PSC_A3 | (k << 9)), 0x0098); + rdata = Afe_read(state, TX_DIAG_TX_DRV | (k << 9)); + rdata &= 0x0600; /* keep bits related to programmable boost */ + rdata |= 0x00C0; + Afe_write(state, (TX_DIAG_TX_DRV | (k << 9)), rdata); + } + } +} + +static u16 aux_cal_cfg(state_struct *state, u16 prev_calib_code) +{ + u16 txpu_calib_code; + u16 txpd_calib_code; + u16 txpu_adj_calib_code; + u16 txpd_adj_calib_code; + u16 new_calib_code; + u16 rdata; + + txpu_calib_code = Afe_read(state, CMN_TXPUCAL_CTRL); + txpd_calib_code = Afe_read(state, CMN_TXPDCAL_CTRL); + txpu_adj_calib_code = Afe_read(state, CMN_TXPU_ADJ_CTRL); + txpd_adj_calib_code = Afe_read(state, CMN_TXPD_ADJ_CTRL); + + new_calib_code = ((txpu_calib_code + txpd_calib_code) / 2) + + txpu_adj_calib_code + txpd_adj_calib_code; + + if (new_calib_code != prev_calib_code) { + rdata = Afe_read(state, TX_ANA_CTRL_REG_1); + rdata &= 0xDFFF; + Afe_write(state, TX_ANA_CTRL_REG_1, rdata); + Afe_write(state, TX_DIG_CTRL_REG_2, new_calib_code); + udelay(10000); + rdata |= 0x2000; + Afe_write(state, TX_ANA_CTRL_REG_1, rdata); + udelay(150); + } + + return new_calib_code; +} + +static void aux_cfg(state_struct *state) +{ + volatile u16 rdata; + + Afe_write(state, TX_DIG_CTRL_REG_2, 36); + + Afe_write(state, TX_ANA_CTRL_REG_2, 0x0100); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_2, 0x0300); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_3, 0x0000); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_1, 0x2008); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_1, 0x2018); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_1, 0xA018); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_2, 0x030C); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_5, 0x0000); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_4, 0x1001); + udelay(150); + Afe_write(state, TX_ANA_CTRL_REG_1, 0xA098); + udelay(5000); + Afe_write(state, TX_ANA_CTRL_REG_1, 0xA198); + udelay(5000); + Afe_write(state, TX_ANA_CTRL_REG_2, 0x030D); + udelay(5000); + Afe_write(state, TX_ANA_CTRL_REG_2, 0x030F); + udelay(5000); + + pr_info("TX_ANA_CTRL_REG_1 %x)\n", rdata); + rdata = Afe_read(state, TX_ANA_CTRL_REG_2); + pr_info("TX_ANA_CTRL_REG_2 %x)\n", rdata); + rdata = Afe_read(state, TX_ANA_CTRL_REG_3); + pr_info("TX_ANA_CTRL_REG_3 %x)\n", rdata); + rdata = Afe_read(state, TX_ANA_CTRL_REG_4); + pr_info("TX_ANA_CTRL_REG_4 %x)\n", rdata); + rdata = Afe_read(state, TX_ANA_CTRL_REG_5); + pr_info("TX_ANA_CTRL_REG_5 %x)\n", rdata); +} + +void AFE_init(state_struct *state, int num_lanes, ENUM_AFE_LINK_RATE link_rate) +{ + volatile u16 val; + + if (AFE_check_rate_supported(link_rate) == 0) { + pr_info + ("AFE_init() *E: Selected link rate not supported: 0x%x\n", + link_rate); + return; + } + val = Afe_read(state, PHY_PMA_CMN_CTRL1); + val = val & 0xFFF7; + val = val | 0x0008; + Afe_write(state, PHY_PMA_CMN_CTRL1, val); + + Afe_write(state, CMN_DIAG_PLL0_TEST_MODE, 0x0022); + Afe_write(state, CMN_PSM_CLK_CTRL, 0x0016); + + phy_cfg_24mhz(state, num_lanes); + + phy_cfg_dp_pll0(state, num_lanes, link_rate); + + val = Afe_read(state, PHY_PMA_CMN_CTRL1); + val = val & 0xFF8F; + val = val | 0x0030; + Afe_write(state, PHY_PMA_CMN_CTRL1, val); + + if (state->edp != 0) + Afe_write(state, CMN_DIAG_CAL_CTRL, 0x0001); + + phy_cfg_dp_ln(state, num_lanes); + + /* Configure PHY in A2 Mode */ + Afe_write(state, PHY_HDP_MODE_CTRL, 0x0004); +} + +void AFE_power(state_struct *state, int num_lanes, + ENUM_AFE_LINK_RATE link_rate) +{ + static u16 prev_calib_code; + + volatile u16 val; + if (AFE_check_rate_supported(link_rate) == 0) { + pr_info + ("AFE_power() *E: Selected link rate not supported: 0x%x\n", + link_rate); + return; + } + + Afe_write(state, TX_DIAG_ACYA_0, 1); + Afe_write(state, TX_DIAG_ACYA_1, 1); + Afe_write(state, TX_DIAG_ACYA_2, 1); + Afe_write(state, TX_DIAG_ACYA_3, 1); + + Afe_write(state, TXDA_CYA_AUXDA_CYA, 1); + + /* Wait for A2 ACK (PHY_HDP_MODE_CTL [6] = 1’b1) */ + do { + val = Afe_read(state, PHY_HDP_MODE_CTRL); + val = val >> 6; + } while ((val & 1) == 0); + + /* to check if PLL has locked (bit 6) */ + val = Afe_read(state, PHY_PMA_CMN_CTRL2); + val = val >> 6; + + if ((val & 1) == 0) { + pr_err("ERROR: PLL is not locked\n"); + } else { + pr_info("PHY_PMA_CMN_CTRL2 = %x\n", val); + } + + /* to check if cmn_ready is asserted (bit 0) */ + val = Afe_read(state, PHY_PMA_CMN_CTRL1); + + if ((val & 1) == 0) { + pr_err("ERROR: cmn_ready is not asserted\n"); + } else { + pr_info("PHY_PMA_CMN_CTRL1 = %x\n", val); + } + + /* Configure PHY in A0 mode (PHY must be in the A0 power state in order to transmit data) */ + Afe_write(state, PHY_HDP_MODE_CTRL, 0x0101); + + /* Wait for A2 ACK (PHY_HDP_MODE_CTL [4] = 1’b1) */ + do { + val = Afe_read(state, PHY_HDP_MODE_CTRL); + val = val >> 4; + } while ((val & 1) == 0); + + prev_calib_code = aux_cal_cfg(state, prev_calib_code); + + aux_cfg(state); + +} |