/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include "mtk_log.h" #include "mtk_drm_crtc.h" #include "mtk_drm_drv.h" #include "mtk_panel_ext.h" #include "mtk_dump.h" #include "mtk_mipi_tx.h" #define MIPITX_DSI_CON 0x00 #define RG_DSI_LDOCORE_EN BIT(0) #define RG_DSI_CKG_LDOOUT_EN BIT(1) #define RG_DSI_BCLK_SEL (3 << 2) #define RG_DSI_LD_IDX_SEL (7 << 4) #define RG_DSI_PHYCLK_SEL (2 << 8) #define RG_DSI_DSICLK_FREQ_SEL BIT(10) #define RG_DSI_LPTX_CLMP_EN BIT(11) #define MIPITX_DSI_CLOCK_LANE 0x04 #define MIPITX_DSI_DATA_LANE0 0x08 #define MIPITX_DSI_DATA_LANE1 0x0c #define MIPITX_DSI_DATA_LANE2 0x10 #define MIPITX_DSI_DATA_LANE3 0x14 #define RG_DSI_LNTx_LDOOUT_EN BIT(0) #define RG_DSI_LNTx_CKLANE_EN BIT(1) #define RG_DSI_LNTx_LPTX_IPLUS1 BIT(2) #define RG_DSI_LNTx_LPTX_IPLUS2 BIT(3) #define RG_DSI_LNTx_LPTX_IMINUS BIT(4) #define RG_DSI_LNTx_LPCD_IPLUS BIT(5) #define RG_DSI_LNTx_LPCD_IMINUS BIT(6) #define RG_DSI_LNTx_RT_CODE (0xf << 8) #define MIPITX_DSI_TOP_CON 0x40 #define RG_DSI_LNT_INTR_EN BIT(0) #define RG_DSI_LNT_HS_BIAS_EN BIT(1) #define RG_DSI_LNT_IMP_CAL_EN BIT(2) #define RG_DSI_LNT_TESTMODE_EN BIT(3) #define RG_DSI_LNT_IMP_CAL_CODE (0xf << 4) #define RG_DSI_LNT_AIO_SEL (7 << 8) #define RG_DSI_PAD_TIE_LOW_EN BIT(11) #define RG_DSI_DEBUG_INPUT_EN BIT(12) #define RG_DSI_PRESERVE (7 << 13) #define MIPITX_DSI_BG_CON 0x44 #define RG_DSI_BG_CORE_EN BIT(0) #define RG_DSI_BG_CKEN BIT(1) #define RG_DSI_BG_DIV (0x3 << 2) #define RG_DSI_BG_FAST_CHARGE BIT(4) #define RG_DSI_VOUT_MSK (0x3ffff << 5) #define RG_DSI_V12_SEL (7 << 5) #define RG_DSI_V10_SEL (7 << 8) #define RG_DSI_V072_SEL (7 << 11) #define RG_DSI_V04_SEL (7 << 14) #define RG_DSI_V032_SEL (7 << 17) #define RG_DSI_V02_SEL (7 << 20) #define RG_DSI_BG_R1_TRIM (0xf << 24) #define RG_DSI_BG_R2_TRIM (0xf << 28) #define MIPITX_DSI_PLL_CON0 0x50 #define RG_DSI_MPPLL_PLL_EN BIT(0) #define RG_DSI_MPPLL_DIV_MSK (0x1ff << 1) #define RG_DSI_MPPLL_PREDIV (3 << 1) #define RG_DSI_MPPLL_TXDIV0 (3 << 3) #define RG_DSI_MPPLL_TXDIV1 (3 << 5) #define RG_DSI_MPPLL_POSDIV (7 << 7) #define RG_DSI_MPPLL_MONVC_EN BIT(10) #define RG_DSI_MPPLL_MONREF_EN BIT(11) #define RG_DSI_MPPLL_VOD_EN BIT(12) #define MIPITX_DSI_PLL_CON1 0x54 #define RG_DSI_MPPLL_SDM_FRA_EN BIT(0) #define RG_DSI_MPPLL_SDM_SSC_PH_INIT BIT(1) #define RG_DSI_MPPLL_SDM_SSC_EN BIT(2) #define RG_DSI_MPPLL_SDM_SSC_PRD (0xffff << 16) #define MIPITX_DSI_PLL_CON2 0x58 /* use to reset DPHY */ #define MIPITX_SW_CTRL_CON4 0x60 #define MIPITX_DSI_PLL_TOP 0x64 #define RG_DSI_MPPLL_PRESERVE (0xff << 8) #define MIPITX_DSI_PLL_PWR 0x68 #define RG_DSI_MPPLL_SDM_PWR_ON BIT(0) #define RG_DSI_MPPLL_SDM_ISO_EN BIT(1) #define RG_DSI_MPPLL_SDM_PWR_ACK BIT(8) #define MIPITX_DSI_SW_CTRL 0x80 #define SW_CTRL_EN BIT(0) #define MIPITX_DSI_SW_CTRL_CON0 0x84 #define SW_LNTC_LPTX_PRE_OE BIT(0) #define SW_LNTC_LPTX_OE BIT(1) #define SW_LNTC_LPTX_P BIT(2) #define SW_LNTC_LPTX_N BIT(3) #define SW_LNTC_HSTX_PRE_OE BIT(4) #define SW_LNTC_HSTX_OE BIT(5) #define SW_LNTC_HSTX_ZEROCLK BIT(6) #define SW_LNT0_LPTX_PRE_OE BIT(7) #define SW_LNT0_LPTX_OE BIT(8) #define SW_LNT0_LPTX_P BIT(9) #define SW_LNT0_LPTX_N BIT(10) #define SW_LNT0_HSTX_PRE_OE BIT(11) #define SW_LNT0_HSTX_OE BIT(12) #define SW_LNT0_LPRX_EN BIT(13) #define SW_LNT1_LPTX_PRE_OE BIT(14) #define SW_LNT1_LPTX_OE BIT(15) #define SW_LNT1_LPTX_P BIT(16) #define SW_LNT1_LPTX_N BIT(17) #define SW_LNT1_HSTX_PRE_OE BIT(18) #define SW_LNT1_HSTX_OE BIT(19) #define SW_LNT2_LPTX_PRE_OE BIT(20) #define SW_LNT2_LPTX_OE BIT(21) #define SW_LNT2_LPTX_P BIT(22) #define SW_LNT2_LPTX_N BIT(23) #define SW_LNT2_HSTX_PRE_OE BIT(24) #define SW_LNT2_HSTX_OE BIT(25) #define MIPITX_LANE_CON (0x000CUL) #define MIPITX_VOLTAGE_SEL (0x0010UL) #define FLD_RG_DSI_HSTX_LDO_REF_SEL (0xf << 6) #define MIPITX_PRESERVED (0x0014UL) #define MIPITX_PLL_PWR (0x0028UL) #define AD_DSI_PLL_SDM_PWR_ON BIT(0) #define AD_DSI_PLL_SDM_ISO_EN BIT(1) #define DA_DSI_PLL_SDM_PWR_ACK BIT(8) #define MIPITX_PLL_CON0 (0x002CUL) #define MIPITX_PLL_CON1 (0x0030UL) #define RG_DSI_PLL_SDM_PCW_CHG BIT(0) #define RG_DSI_PLL_EN BIT(4) #define MIPITX_PLL_CON2 (0x0034UL) #define MIPITX_PLL_CON3 (0x0038UL) #define MIPITX_PLL_CON4 (0x003CUL) #define MIPITX_D2_SW_CTL_EN (0x0144UL) #define DSI_D2_SW_CTL_EN BIT(0) #define MIPITX_D0_SW_CTL_EN (0x0244UL) #define DSI_D0_SW_CTL_EN BIT(0) #define MIPITX_CK_SW_CTL_EN (0x0344UL) #define DSI_CK_SW_CTL_EN BIT(0) #define MIPITX_D1_SW_CTL_EN (0x0444UL) #define DSI_D1_SW_CTL_EN BIT(0) #define MIPITX_D3_SW_CTL_EN (0x0544UL) #define DSI_D3_SW_CTL_EN BIT(0) #define MIPITX_PHY_SEL0 (0x0040UL) #define FLD_MIPI_TX_CPHY_EN (0x1 << 0) #define FLD_MIPI_TX_PHY2_SEL (0xf << 4) #define FLD_MIPI_TX_CPHY0BC_SEL (0xf << 8) #define FLD_MIPI_TX_PHY0_SEL (0xf << 12) #define FLD_MIPI_TX_PHY1AB_SEL (0xf << 16) #define FLD_MIPI_TX_PHYC_SEL (0xf << 20) #define FLD_MIPI_TX_CPHY1CA_SEL (0xf << 24) #define FLD_MIPI_TX_PHY1_SEL (0xf << 28) #define MIPITX_PHY_SEL1 (0x0044UL) #define FLD_MIPI_TX_PHY2BC_SEL (0xf << 0) #define FLD_MIPI_TX_PHY3_SEL (0xf << 4) #define FLD_MIPI_TX_CPHYXXX_SEL (0xf << 8) #define FLD_MIPI_TX_LPRX0AB_SEL (0xf << 12) #define FLD_MIPI_TX_LPRX0BC_SEL (0xf << 16) #define FLD_MIPI_TX_LPRX0CA_SEL (0xf << 20) #define FLD_MIPI_TX_CPHY0_HS_SEL (0xf << 24) #define FLD_MIPI_TX_CPHY1_HS_SEL (0xf << 26) #define FLD_MIPI_TX_CPHY2_HS_SEL (0xf << 28) #define MIPITX_PHY_SEL2 (0x0048UL) #define FLD_MIPI_TX_PHY2_HSDATA_SEL (0xf << 0) #define FLD_MIPI_TX_CPHY0BC_HSDATA_SEL (0xf << 4) #define FLD_MIPI_TX_PHY0_HSDATA_SEL (0xf << 8) #define FLD_MIPI_TX_PHY1AB_HSDATA_SEL (0xf << 12) #define FLD_MIPI_TX_PHYC_HSDATA_SEL (0xf << 16) #define FLD_MIPI_TX_CPHY1CA_HSDATA_SEL (0xf << 20) #define FLD_MIPI_TX_PHY1_HSDATA_SEL (0xf << 24) #define FLD_MIPI_TX_PHY2BC_HSDATA_SEL (0xf << 28) #define MIPITX_PHY_SEL3 (0x004CUL) #define FLD_MIPI_TX_PHY3_HSDATA_SEL (0xf << 0) #define MIPITX_D2P_RTCODE0 (0x0100UL) #define MIPITX_D2N_RTCODE0 (0x0114UL) #define MIPITX_D2P_RT_DEM_CODE (0x01C8UL) #define MIPITX_D2N_RT_DEM_CODE (0x01CCUL) #define MIPITX_D2_CKMODE_EN (0x0128UL) #define MIPITX_D0_CKMODE_EN (0x0228UL) #define MIPITX_CK_CKMODE_EN (0x0328UL) #define MIPITX_D1_CKMODE_EN (0x0428UL) #define MIPITX_D3_CKMODE_EN (0x0528UL) #define FLD_DSI_SW_CTL_EN BIT(0) #define FLD_AD_DSI_PLL_SDM_PWR_ON BIT(0) #define FLD_AD_DSI_PLL_SDM_ISO_EN BIT(1) #define FLD_RG_DSI_PLL_POSDIV (0x7 << 8) #define FLD_RG_DSI_PLL_POSDIV_ REG_FLD_MSB_LSB(10, 8) #define MIPITX_D0_SW_LPTX_PRE_OE (0x0248UL) #define MIPITX_D0C_SW_LPTX_PRE_OE (0x0268UL) #define MIPITX_D1_SW_LPTX_PRE_OE (0x0448UL) #define MIPITX_D1C_SW_LPTX_PRE_OE (0x0468UL) #define MIPITX_D2_SW_LPTX_PRE_OE (0x0148UL) #define MIPITX_D2C_SW_LPTX_PRE_OE (0x0168UL) #define MIPITX_D3_SW_LPTX_PRE_OE (0x0548UL) #define MIPITX_D3C_SW_LPTX_PRE_OE (0x0568UL) #define MIPITX_CK_SW_LPTX_PRE_OE (0x0348UL) #define MIPITX_CKC_SW_LPTX_PRE_OE (0x0368UL) enum MIPITX_PAD_VALUE { PAD_D2P_T0A = 0, PAD_D2N_T0B, PAD_D0P_T0C, PAD_D0N_T1A, PAD_CKP_T1B, PAD_CKN_T1C, PAD_D1P_T2A, PAD_D1N_T2B, PAD_D3P_T2C, PAD_D3N_XXX, PAD_NUM }; struct mtk_mipitx_data { const u32 mppll_preserve; int (*pll_prepare)(struct clk_hw *hw); int (*power_on_signal)(struct phy *phy); void (*pll_unprepare)(struct clk_hw *hw); int (*power_off_signal)(struct phy *phy); }; struct mtk_mipi_tx { struct device *dev; void __iomem *regs; resource_size_t regs_pa; struct cmdq_base *cmdq_base; u32 data_rate; u32 data_rate_adpt; const struct mtk_mipitx_data *driver_data; struct clk_hw pll_hw; struct clk *pll; }; static inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw) { return container_of(hw, struct mtk_mipi_tx, pll_hw); } static void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 bits) { u32 temp = readl(mipi_tx->regs + offset); writel(temp & ~bits, mipi_tx->regs + offset); } static void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 bits) { u32 temp = readl(mipi_tx->regs + offset); writel(temp | bits, mipi_tx->regs + offset); } static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 mask, u32 data) { u32 temp = readl(mipi_tx->regs + offset); writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset); } unsigned int mtk_mipi_tx_pll_get_rate(struct phy *phy) { #ifndef CONFIG_FPGA_EARLY_PORTING int i = 0; unsigned int pcw; unsigned int prediv; unsigned int posdiv; struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); pcw = readl(mipi_tx->regs + MIPITX_PLL_CON0); pcw = (pcw >> 24) & 0xff; prediv = 1; posdiv = DISP_REG_GET_FIELD(FLD_RG_DSI_PLL_POSDIV_, MIPITX_PLL_CON1 + mipi_tx->regs); posdiv = (1 << posdiv); DDPINFO("%s, pcw: %d, prediv: %d, posdiv: %d", __func__, pcw, prediv, posdiv); i = prediv * posdiv; if (i > 0) return 26 * pcw / i; #endif /* CONFIG_FPGA_EARLY_PORTING */ return 0; } int mtk_mipi_tx_dump(struct phy *phy) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); int k; DDPDUMP("== MIPI REGS ==\n"); for (k = 0; k < 0x6A0; k += 16) { DDPDUMP("0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x\n", k, readl(mipi_tx->regs + k), readl(mipi_tx->regs + k + 0x4), readl(mipi_tx->regs + k + 0x8), readl(mipi_tx->regs + k + 0xc)); } return 0; } int mtk_mipi_tx_cphy_lane_config(struct phy *phy, struct mtk_panel_ext *mtk_panel, bool is_master) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); struct mtk_panel_params *params = mtk_panel->params; int i = 0; enum MIPITX_PHY_LANE_SWAP *swap_base; enum MIPITX_PAD_VALUE pad_mapping[MIPITX_PHY_LANE_NUM] = { PAD_D2P_T0A, PAD_D0N_T1A, PAD_D1P_T2A, PAD_D1P_T2A, PAD_D1P_T2A, PAD_D1P_T2A}; /* TODO: support dual port MIPI lane_swap */ swap_base = params->lane_swap[i]; DDPINFO("%s+\n", __func__); DDPDBG("MIPITX Lane Swap Enabled for DSI Port %d\n", i); DDPDBG("MIPITX Lane Swap mapping: %d|%d|%d|%d|%d|%d\n", swap_base[MIPITX_PHY_LANE_0], swap_base[MIPITX_PHY_LANE_1], swap_base[MIPITX_PHY_LANE_2], swap_base[MIPITX_PHY_LANE_3], swap_base[MIPITX_PHY_LANE_CK], swap_base[MIPITX_PHY_LANE_RX]); /*set lane swap*/ if (!mtk_panel->params->lane_swap_en) { writel(0x65432101, mipi_tx->regs + MIPITX_PHY_SEL0); writel(0x24210987, mipi_tx->regs + MIPITX_PHY_SEL1); writel(0x68543102, mipi_tx->regs + MIPITX_PHY_SEL2); writel(0x00000007, mipi_tx->regs + MIPITX_PHY_SEL3); return 0; } /* ENABLE CPHY*/ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, 0x1, 0x1); /* CPHY_LANE_T0 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY2_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]]) << 4); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_CPHY0BC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 1) << 8); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY0_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 2) << 12); /* CPHY_LANE_T1 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY1AB_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]]) << 16); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHYC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]] + 1) << 20); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_CPHY1CA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]] + 2) << 24); /* CPHY_LANE_T2 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY1_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]]) << 28); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_PHY2BC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]] + 1) << 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_PHY3_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]] + 2) << 4); /* LPRX SETTING */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_LPRX0AB_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]]) << 12); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_LPRX0BC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 1) << 16); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_LPRX0CA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 2) << 20); /* HS SETTING */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_CPHY0_HS_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]]) / 3 << 24); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_CPHY1_HS_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]] / 3) << 26); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_CPHY2_HS_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]] / 3) << 28); /* HS_DATA_SETTING */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY2_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 2) << 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_CPHY0BC_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]]) << 4); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY0_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 1) << 8); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY1AB_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]]) << 12); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHYC_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]] + 1) << 16); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_CPHY1CA_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]] + 2) << 20); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY1_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]] + 2) << 24); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY2BC_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]]) << 28); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL3, FLD_MIPI_TX_PHY3_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]] + 1) << 0); return 0; } int mtk_mipi_tx_dphy_lane_config(struct phy *phy, struct mtk_panel_ext *mtk_panel, bool is_master) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); struct mtk_panel_params *params = mtk_panel->params; int j, i = 0; enum MIPITX_PHY_LANE_SWAP *swap_base; enum MIPITX_PAD_VALUE pad_mapping[MIPITX_PHY_LANE_NUM] = { PAD_D0P_T0C, PAD_D1P_T2A, PAD_D2P_T0A, PAD_D3P_T2C, PAD_CKP_T1B, PAD_CKP_T1B}; if (!mtk_panel->params->lane_swap_en) { mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_CKMODE_EN, 0x1, 0x1); return 0; } /* TODO: support dual port MIPI lane_swap */ if (is_master) swap_base = params->lane_swap[MIPITX_PHY_PORT_0]; else swap_base = params->lane_swap[MIPITX_PHY_PORT_1]; DDPDBG("MIPITX Lane Swap Enabled for DSI Port %d\n", i); DDPDBG("MIPITX Lane Swap mapping: %d|%d|%d|%d|%d|%d\n", swap_base[MIPITX_PHY_LANE_0], swap_base[MIPITX_PHY_LANE_1], swap_base[MIPITX_PHY_LANE_2], swap_base[MIPITX_PHY_LANE_3], swap_base[MIPITX_PHY_LANE_CK], swap_base[MIPITX_PHY_LANE_RX]); for (j = MIPITX_PHY_LANE_0; j < MIPITX_PHY_LANE_CK; j++) { if (swap_base[j] == MIPITX_PHY_LANE_CK) break; } switch (j) { case MIPITX_PHY_LANE_0: mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_CKMODE_EN, 0x1, 0x1); break; case MIPITX_PHY_LANE_1: mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_CKMODE_EN, 0x1, 0x1); break; case MIPITX_PHY_LANE_2: mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_CKMODE_EN, 0x1, 0x1); break; case MIPITX_PHY_LANE_3: mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_CKMODE_EN, 0x1, 0x1); break; case MIPITX_PHY_LANE_CK: mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_CKMODE_EN, 0x1, 0x1); break; default: break; } /* LANE_0 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY0_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]]) << 12); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY1AB_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]] + 1) << 16); /* LANE_1 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY1_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]]) << 28); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_PHY2BC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]] + 1) << 0); /* LANE_2 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHY2_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]]) << 4); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_CPHY0BC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]] + 1) << 8); /* LANE_3 */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_PHY3_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_3]]) << 4); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_CPHYXXX_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_3]] + 1) << 8); /* CK_LANE */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_PHYC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_CK]]) << 20); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL0, FLD_MIPI_TX_CPHY1CA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_CK]] + 1) << 24); /* LPRX SETTING */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_LPRX0AB_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_RX]]) << 12); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL1, FLD_MIPI_TX_LPRX0BC_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_RX]] + 1) << 16); /* HS_DATA_SETTING */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY2_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_2]]) << 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY0_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_0]]) << 8); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHYC_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_CK]]) << 16); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL2, FLD_MIPI_TX_PHY1_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_1]]) << 24); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PHY_SEL3, FLD_MIPI_TX_PHY3_HSDATA_SEL, (pad_mapping[swap_base[MIPITX_PHY_LANE_3]]) << 0); return 0; } void mtk_mipi_tx_sw_control_en(struct phy *phy, bool en) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); if (en) { mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); } else { mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); } } void mtk_mipi_tx_pre_oe_config(struct phy *phy, bool en) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); if (en) { mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2C_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0C_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CKC_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1C_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3C_SW_LPTX_PRE_OE, 1); } else { mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2C_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0C_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CKC_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1C_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_LPTX_PRE_OE, 1); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3C_SW_LPTX_PRE_OE, 1); } } static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); u8 txdiv, txdiv0, txdiv1; u64 pcw; dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); if (mipi_tx->data_rate >= 500000000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (mipi_tx->data_rate >= 250000000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (mipi_tx->data_rate >= 125000000) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (mipi_tx->data_rate > 62000000) { txdiv = 8; txdiv0 = 2; txdiv1 = 1; } else if (mipi_tx->data_rate >= 50000000) { txdiv = 16; txdiv0 = 2; txdiv1 = 2; } else { return -EINVAL; } mtk_mipi_tx_update_bits( mipi_tx, MIPITX_DSI_BG_CON, RG_DSI_VOUT_MSK | RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN, (4 << 20) | (4 << 17) | (4 << 14) | (4 << 11) | (4 << 8) | (4 << 5) | RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON, RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN, (8 << 4) | RG_DSI_LNT_HS_BIAS_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON, RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, RG_DSI_MPPLL_SDM_PWR_ON | RG_DSI_MPPLL_SDM_ISO_EN, RG_DSI_MPPLL_SDM_PWR_ON); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 | RG_DSI_MPPLL_PREDIV, (txdiv0 << 3) | (txdiv1 << 5)); /* * PLL PCW config * PCW bit 24~30 = integer part of pcw * PCW bit 0~23 = fractional part of pcw * pcw = data_Rate*4*txdiv/(Ref_clk*2); * Post DIV =4, so need data_Rate*4 * Ref_clk is 26MHz */ pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24, 26000000); writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1, RG_DSI_MPPLL_SDM_FRA_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN); usleep_range(20, 100); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1, RG_DSI_MPPLL_SDM_SSC_EN); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, RG_DSI_MPPLL_PRESERVE, mipi_tx->driver_data->mppll_preserve); return 0; } static bool mtk_is_mipi_tx_enable(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); u32 tmp = readl(mipi_tx->regs + MIPITX_PLL_CON1); return ((tmp & RG_DSI_PLL_EN) > 0); } inline unsigned int _dsi_get_pcw(unsigned long data_rate, unsigned int pcw_ratio) { unsigned int pcw, tmp, pcw_floor; /** * PCW bit 24~30 = floor(pcw) * PCW bit 16~23 = (pcw - floor(pcw))*256 * PCW bit 8~15 = (pcw*256 - floor(pcw)*256)*256 * PCW bit 0~7 = (pcw*256*256 - floor(pcw)*256*256)*256 */ pcw = data_rate * pcw_ratio / 26; pcw_floor = data_rate * pcw_ratio % 26; tmp = ((pcw & 0xFF) << 24) | (((256 * pcw_floor / 26) & 0xFF) << 16) | (((256 * (256 * pcw_floor % 26) / 26) & 0xFF) << 8) | ((256 * (256 * (256 * pcw_floor % 26) % 26) / 26) & 0xFF); return tmp; } static int mtk_mipi_tx_pll_prepare_mt6779(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u64 pcw; DDPINFO("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); if (mipi_tx->data_rate >= 2000000000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (mipi_tx->data_rate >= 1000000000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (mipi_tx->data_rate >= 500000000) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (mipi_tx->data_rate > 250000000) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (mipi_tx->data_rate >= 125000000) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 0); /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); pcw = (mipi_tx->data_rate / 1000000) * txdiv / 26; tmp = ((pcw & 0xFF) << 24) | (((256 * ((mipi_tx->data_rate / 1000000) * txdiv % 26) / 26) & 0xFF) << 16) | (((256 * (256 * ((mipi_tx->data_rate / 1000000) * txdiv % 26) % 26) / 26) & 0xFF) << 8) | ((256 * (256 * (256 * ((mipi_tx->data_rate / 1000000) * txdiv % 26) % 26) % 26) / 26) & 0xFF); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); DDPINFO("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_prepare_mt6885(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); #if 1 /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); #endif /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); /* TODO: should write bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); DDPDBG("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_cphy_prepare_mt6885(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } /*set volate: cphy need 500mV*/ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL, FLD_RG_DSI_HSTX_LDO_REF_SEL, 0xD << 6); /* change the mipi_volt */ if (mipi_volt) { DDPMSG("%s+ mipi_volt change: %d\n", __func__, mipi_volt); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL, FLD_RG_DSI_HSTX_LDO_REF_SEL, mipi_volt << 6); } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); /* step 0 */ /* BG_LPF_EN / BG_CORE_EN */ writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN=0 BG_CORE_EN=1 */ writel(0x3FFF0088, mipi_tx->regs + MIPITX_LANE_CON); //usleep_range(1, 1); /* 1us */ /* BG_LPF_EN=1 */ writel(0x3FFF00C8, mipi_tx->regs + MIPITX_LANE_CON); /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); DDPDBG("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_prepare_mt6873(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); #if 1 /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); #endif /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); /* TODO: should write bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); if (mipi_volt) { /* set mipi_tx voltage */ DDPMSG(" %s+ mipi_volt change: %d\n", __func__, mipi_volt); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL, FLD_RG_DSI_HSTX_LDO_REF_SEL, mipi_volt << 6); } DDPDBG("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_cphy_prepare_mt6873(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } /*set volate*/ #if defined(CONFIG_TB8791TP1_TITAN_JAVAN_TIGER) writel(0x444423EA, mipi_tx->regs + MIPITX_VOLTAGE_SEL); DDPMSG("%s : Enhance mipi_volt\n", __func__); #else writel(0x4444236A, mipi_tx->regs + MIPITX_VOLTAGE_SEL); #endif /* change the mipi_volt */ if (mipi_volt) { DDPMSG("%s+ mipi_volt change: %d\n", __func__, mipi_volt); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL, FLD_RG_DSI_HSTX_LDO_REF_SEL, mipi_volt<<6); } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); /* step 0 */ /* BG_LPF_EN / BG_CORE_EN */ writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN=0 BG_CORE_EN=1 */ writel(0x3FFF0088, mipi_tx->regs + MIPITX_LANE_CON); //usleep_range(1, 1); /* 1us */ /* BG_LPF_EN=1 */ writel(0x3FFF00C8, mipi_tx->regs + MIPITX_LANE_CON); /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); DDPDBG("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_prepare_mt6853(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); #if 1 /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); #endif /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); /* TODO: should write bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); DDPDBG("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_prepare_mt6877(struct clk_hw *hw) { #ifndef CONFIG_FPGA_EARLY_PORTING struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); #if 1 /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); #endif /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); /* TODO: should write bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); DDPDBG("%s-\n", __func__); #endif return 0; } static int mtk_mipi_tx_pll_prepare_mt6781(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; DDPINFO( "prepare: %u MHz, mipi_tx->data_rate_adpt: %d MHz, mipi_tx->data_rate : %d MHz\n", rate, mipi_tx->data_rate_adpt, (mipi_tx->data_rate / 1000000)); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x0, mipi_tx->regs + MIPITX_PRESERVED); writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); #if 1 /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); #endif /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); /* TODO: should write bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); DDPDBG("%s-\n", __func__); return 0; } static int mtk_mipi_tx_pll_prepare_mt6833(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 rate; DDPDBG("%s+\n", __func__); /* if mipitx is on, skip it... */ if (mtk_is_mipi_tx_enable(hw)) { DDPINFO("%s: mipitx already on\n", __func__); return 0; } rate = (mipi_tx->data_rate_adpt) ? mipi_tx->data_rate_adpt : mipi_tx->data_rate / 1000000; dev_dbg(mipi_tx->dev, "prepare: %u MHz\n", rate); if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return -EINVAL; } writel(0x00FF12E0, mipi_tx->regs + MIPITX_PLL_CON4); /* BG_LPF_EN / BG_CORE_EN */ writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); usleep_range(500, 600); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); #if 1 /* Switch OFF each Lane */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, FLD_DSI_SW_CTL_EN, 1); #endif /* step 1: SDM_RWR_ON / SDM_ISO_EN */ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_PWR_ON, 1); usleep_range(30, 100); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_PWR, FLD_AD_DSI_PLL_SDM_ISO_EN, 0); tmp = _dsi_get_pcw(rate, txdiv); writel(tmp, mipi_tx->regs + MIPITX_PLL_CON0); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, FLD_RG_DSI_PLL_POSDIV, txdiv0 << 8); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); usleep_range(50, 100); /* TODO: should write bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_set_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); DDPDBG("%s-\n", __func__); return 0; } static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, RG_DSI_MPPLL_PRESERVE, mipi_tx->driver_data->mppll_preserve); mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, RG_DSI_MPPLL_SDM_ISO_EN | RG_DSI_MPPLL_SDM_PWR_ON, RG_DSI_MPPLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON, RG_DSI_LNT_HS_BIAS_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_CON, RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_BG_CON, RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_DIV_MSK); } static void mtk_mipi_tx_pll_unprepare_mt6779(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPINFO("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_unprepare_mt6885(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); /* TODO: should clear bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); #if 0 mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); #endif writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_cphy_unprepare_mt6885(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "cphy unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0000, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_unprepare_mt6873(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); /* TODO: should clear bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); #if 0 mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); #endif writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_cphy_unprepare_mt6873(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "cphy unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); writel(0x3FFF0080, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0000, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_unprepare_mt6853(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); /* TODO: should clear bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); #if 0 mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); #endif writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_unprepare_mt6877(struct clk_hw *hw) { #ifndef CONFIG_FPGA_EARLY_PORTING struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); /* TODO: should clear bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); #endif } static void mtk_mipi_tx_pll_unprepare_mt6833(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); /* TODO: should clear bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); #if 0 mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); #endif writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPINFO("%s-\n", __func__); } static void mtk_mipi_tx_pll_unprepare_mt6781(struct clk_hw *hw) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s+\n", __func__); dev_dbg(mipi_tx->dev, "unprepare\n"); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); /* TODO: should clear bit8 to set SW_ANA_CK_EN here */ mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_SW_CTRL_CON4, 1); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); #if 0 mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_D0_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_D1_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_D2_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_D3_SW_CTL_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_CK_SW_CTL_EN); #endif writel(0x3FFF0180, mipi_tx->regs + MIPITX_LANE_CON); writel(0x3FFF0100, mipi_tx->regs + MIPITX_LANE_CON); DDPDBG("%s-\n", __func__); } void mtk_mipi_tx_pll_rate_set_adpt(struct phy *phy, unsigned long rate) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); DDPDBG("%s set rate: %lu Hz\n", __func__, rate); mipi_tx->data_rate_adpt = rate; } void mtk_mipi_tx_pll_rate_switch_gce(struct phy *phy, void *handle, unsigned long rate) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); unsigned int txdiv, txdiv0, txdiv1, tmp; u32 reg_val; DDPMSG("%s+ %lu\n", __func__, rate); /* parameter rate should be MHz */ if (rate >= 2000) { txdiv = 1; txdiv0 = 0; txdiv1 = 0; } else if (rate >= 1000) { txdiv = 2; txdiv0 = 1; txdiv1 = 0; } else if (rate >= 500) { txdiv = 4; txdiv0 = 2; txdiv1 = 0; } else if (rate > 250) { txdiv = 8; txdiv0 = 3; txdiv1 = 0; } else if (rate >= 125) { txdiv = 16; txdiv0 = 4; txdiv1 = 0; } else { return; } tmp = _dsi_get_pcw(rate, txdiv); cmdq_pkt_write(handle, mipi_tx->cmdq_base, mipi_tx->regs_pa + MIPITX_PLL_CON0, tmp, ~0); reg_val = readl(mipi_tx->regs + MIPITX_PLL_CON1); reg_val = ((reg_val & ~FLD_RG_DSI_PLL_POSDIV) | ((txdiv0 << 8) & FLD_RG_DSI_PLL_POSDIV)); reg_val = (reg_val & ~RG_DSI_PLL_SDM_PCW_CHG) | (0 & RG_DSI_PLL_SDM_PCW_CHG); cmdq_pkt_write(handle, mipi_tx->cmdq_base, mipi_tx->regs_pa + MIPITX_PLL_CON1, reg_val, ~0); reg_val = (reg_val & ~RG_DSI_PLL_SDM_PCW_CHG) | (1 & RG_DSI_PLL_SDM_PCW_CHG); cmdq_pkt_write(handle, mipi_tx->cmdq_base, mipi_tx->regs_pa + MIPITX_PLL_CON1, reg_val, ~0); reg_val = (reg_val & ~RG_DSI_PLL_SDM_PCW_CHG) | (0 & RG_DSI_PLL_SDM_PCW_CHG); cmdq_pkt_write(handle, mipi_tx->cmdq_base, mipi_tx->regs_pa + MIPITX_PLL_CON1, reg_val, ~0); DDPMSG("%s-\n", __func__); } static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { #ifndef CONFIG_MTK_MT6382_BDG return clamp_val(rate, 50000000, 1250000000); #else return clamp_val(rate, 50000000, 2300000000); #endif } static int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); DDPDBG("%s set rate: %lu Hz\n", __func__, rate); dev_dbg(mipi_tx->dev, "set rate: %lu Hz\n", rate); mipi_tx->data_rate = rate; return 0; } static unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); return mipi_tx->data_rate; } static struct clk_ops mtk_mipi_tx_pll_ops = { .unprepare = mtk_mipi_tx_pll_unprepare, .round_rate = mtk_mipi_tx_pll_round_rate, .set_rate = mtk_mipi_tx_pll_set_rate, .recalc_rate = mtk_mipi_tx_pll_recalc_rate, }; static int mtk_mipi_tx_power_on_signal(struct phy *phy) { #if !defined(CONFIG_MACH_MT6885) && !defined(CONFIG_MACH_MT6873) \ && !defined(CONFIG_MACH_MT6893) && !defined(CONFIG_MACH_MT6853) \ && !defined(CONFIG_MACH_MT6833) && !defined(CONFIG_MACH_MT6877) \ && !defined(CONFIG_MACH_MT6781) struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); u32 reg; for (reg = MIPITX_DSI_CLOCK_LANE; reg <= MIPITX_DSI_DATA_LANE3; reg += 4) mtk_mipi_tx_set_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON, RG_DSI_PAD_TIE_LOW_EN); #endif return 0; } #ifdef MTK_FILL_MIPI_IMPEDANCE unsigned int rt_code_backup0[2][25]; unsigned int rt_code_backup1[2][25]; unsigned int rt_dem_code_backup0[2][5]; unsigned int rt_dem_code_backup1[2][5]; #define SECOND_PHY_OFFSET (0x10000UL) static void backup_mipitx_impedance(struct mtk_mipi_tx *mipi_tx) { unsigned int i = 0; unsigned int j = 0; unsigned int k = 0; /* backup mipitx impedance */ for (i = 0; i < 2; i++) { if (i == 0) { for (j = 0; j < 5; j++) for (k = 0; k < 5; k++) { rt_code_backup0[0][j*5 + k] = readl(mipi_tx->regs + MIPITX_D2P_RTCODE0 + k * 0x4 + j * 0x100); rt_code_backup1[0][j*5 + k] = readl(mipi_tx->regs + MIPITX_D2N_RTCODE0 + k * 0x4 + j * 0x100); } } else { for (j = 0; j < 5; j++) { rt_dem_code_backup0[0][j] = readl(mipi_tx->regs + MIPITX_D2P_RT_DEM_CODE + j * 0x100); rt_dem_code_backup1[0][j] = readl(mipi_tx->regs + MIPITX_D2N_RT_DEM_CODE + j * 0x100); } } } #if 0 /* Verification log */ for (i = 0; i < 10; i++) { if (i < 5) k = i * 0x100; else k = (i - 5) * 0x100; if (i < 5) { DDPDUMP("MIPI_TX "); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2P_RTCODE0 + k, readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0x10))); DDPDUMP("MIPI_TX2"); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2N_RTCODE0 + k, readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0x10))); } else { DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2P_RT_DEM_CODE + k, readl((mipi_tx->regs + MIPITX_D2P_RT_DEM_CODE + k))); DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2N_RT_DEM_CODE + k, readl((mipi_tx->regs + MIPITX_D2N_RT_DEM_CODE + k))); } } #endif /* mipitx impedance print */ #if defined(CONFIG_MACH_MT6885) || defined(CONFIG_MACH_MT6893) #if 0 /* Second mipi tx is not currently in use */ /* backup second mipitx impedance */ for (i = 0; i < 2; i++) { if (i == 0) { for (j = 0; j < 5; j++) for (k = 0; k < 5; k++) { rt_code_backup0[1][j*5 + k] = readl(mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k * 0x4 + j * 0x100); rt_code_backup1[1][j*5 + k] = readl(mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k * 0x4 + j * 0x100); } } else { for (j = 0; j < 5; j++) { rt_dem_code_backup0[1][j] = readl(mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RT_DEM_CODE + j * 0x100); rt_dem_code_backup1[1][j] = readl(mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RT_DEM_CODE + j * 0x100); } } } #endif /* sedond mipi tx is not currently in use */ #if 0 /* Verification log */ for (i = 0; i < 10; i++) { if (i < 5) k = i * 0x100; else k = (i - 5) * 0x100; if (i < 5) { DDPDUMP("MIPI_TX "); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0x10))); DDPDUMP("MIPI_TX2"); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0x10))); } else { DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2P_RT_DEM_CODE + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RT_DEM_CODE + k))); DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2N_RT_DEM_CODE + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RT_DEM_CODE + k))); } } #endif /* second mipitx impedance print */ #endif /* end define MACH_MT6885 */ } static void refill_mipitx_impedance(struct mtk_mipi_tx *mipi_tx) { unsigned int i = 0; unsigned int j = 0; unsigned int k = 0; /* backup mipitx impedance */ for (i = 0; i < 2; i++) { if (i == 0) { for (j = 0; j < 5; j++) for (k = 0; k < 5; k++) { writel(rt_code_backup0[0][j*5 + k], (mipi_tx->regs + MIPITX_D2P_RTCODE0 + k * 0x4 + j * 0x100)); writel(rt_code_backup1[0][j*5 + k], (mipi_tx->regs + MIPITX_D2N_RTCODE0 + k * 0x4 + j * 0x100)); } } else { for (j = 0; j < 5; j++) { writel(rt_dem_code_backup0[0][j], (mipi_tx->regs + MIPITX_D2P_RT_DEM_CODE + j * 0x100)); writel(rt_dem_code_backup1[0][j], (mipi_tx->regs + MIPITX_D2N_RT_DEM_CODE + j * 0x100)); } } } #if 0 /* Verification log */ for (i = 0; i < 10; i++) { if (i < 5) k = i * 0x100; else k = (i - 5) * 0x100; if (i < 5) { DDPDUMP("MIPI_TX "); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2P_RTCODE0 + k, readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + MIPITX_D2P_RTCODE0 + k + 0x10))); DDPDUMP("MIPI_TX2"); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2N_RTCODE0 + k, readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + MIPITX_D2N_RTCODE0 + k + 0x10))); } else { DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2P_RT_DEM_CODE + k, readl((mipi_tx->regs + MIPITX_D2P_RT_DEM_CODE + k))); DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + MIPITX_D2N_RT_DEM_CODE + k, readl((mipi_tx->regs + MIPITX_D2N_RT_DEM_CODE + k))); } } #endif /* mipitx impedance print */ #if defined(CONFIG_MACH_MT6885) || defined(CONFIG_MACH_MT6893) #if 0 /* Second mipi tx is not currently in use */ /* refill second mipitx impedance */ for (i = 0; i < 2; i++) { if (i == 0) { for (j = 0; j < 5; j++) for (k = 0; k < 5; k++) { writel(rt_code_backup0[1][j*5 + k], (mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k * 0x4 + j * 0x100)); writel(rt_code_backup1[1][j*5 + k], (mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k * 0x4 + j * 0x100)); } } else { for (j = 0; j < 5; j++) { writel(rt_dem_code_backup0[1][j], (mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RT_DEM_CODE + j * 0x100)); writel(rt_dem_code_backup1[1][j], (mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RT_DEM_CODE + j * 0x100)); } } } #endif /* Second mipi tx is not currently in use */ #if 0 /* Verification log */ for (i = 0; i < 10; i++) { if (i < 5) k = i * 0x100; else k = (i - 5) * 0x100; if (i < 5) { DDPDUMP("MIPI_TX "); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RTCODE0 + k + 0x10))); DDPDUMP("MIPI_TX2"); DDPDUMP("[0x%08x]:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0x4)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0x8)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0xC)), readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RTCODE0 + k + 0x10))); } else { DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2P_RT_DEM_CODE + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2P_RT_DEM_CODE + k))); DDPDUMP("MIPI_TX[0x%08x]: 0x%08x\n", mipi_tx->regs_pa + SECOND_PHY_OFFSET + MIPITX_D2N_RT_DEM_CODE + k, readl((mipi_tx->regs + SECOND_PHY_OFFSET + MIPITX_D2N_RT_DEM_CODE + k))); } } #endif /* second mipitx impedance print */ #endif /* end define MACH_MT6885 */ } #endif static int mtk_mipi_tx_power_on(struct phy *phy) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); int ret; /* Power up core and enable PLL */ ret = clk_prepare_enable(mipi_tx->pll); if (ret < 0) return ret; /* Enable DSI Lane LDO outputs, disable pad tie low */ if (mipi_tx->driver_data->power_on_signal) mipi_tx->driver_data->power_on_signal(phy); #ifdef MTK_FILL_MIPI_IMPEDANCE refill_mipitx_impedance(mipi_tx); #endif return 0; } static void mtk_mipi_tx_power_off_signal(struct phy *phy) { #if !defined(CONFIG_MACH_MT6885) && !defined(CONFIG_MACH_MT6873) \ && !defined(CONFIG_MACH_MT6893) && !defined(CONFIG_MACH_MT6853) \ && !defined(CONFIG_MACH_MT6833) && !defined(CONFIG_MACH_MT6877) \ && !defined(CONFIG_MACH_MT6781) struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); u32 reg; mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON, RG_DSI_PAD_TIE_LOW_EN); for (reg = MIPITX_DSI_CLOCK_LANE; reg <= MIPITX_DSI_DATA_LANE3; reg += 4) mtk_mipi_tx_clear_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN); #endif } static int mtk_mipi_tx_power_off(struct phy *phy) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); /* Enable pad tie low, disable DSI Lane LDO outputs */ mtk_mipi_tx_power_off_signal(phy); /* Disable PLL and power down core */ clk_disable_unprepare(mipi_tx->pll); return 0; } static const struct phy_ops mtk_mipi_tx_ops = { .power_on = mtk_mipi_tx_power_on, .power_off = mtk_mipi_tx_power_off, .owner = THIS_MODULE, }; static int mtk_mipi_tx_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mtk_mipi_tx *mipi_tx; struct resource *mem; struct clk *ref_clk; const char *ref_clk_name; struct clk_init_data clk_init = { .ops = &mtk_mipi_tx_pll_ops, .num_parents = 1, .parent_names = (const char *const *)&ref_clk_name, .flags = CLK_SET_RATE_GATE, }; struct phy *phy; struct phy_provider *phy_provider; int ret; DDPINFO("%s+\n", __func__); mipi_tx = devm_kzalloc(dev, sizeof(*mipi_tx), GFP_KERNEL); if (!mipi_tx) return -ENOMEM; mipi_tx->driver_data = (struct mtk_mipitx_data *)of_device_get_match_data(&pdev->dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mipi_tx->regs = devm_ioremap_resource(dev, mem); if (IS_ERR(mipi_tx->regs)) { ret = PTR_ERR(mipi_tx->regs); dev_err(dev, "Failed to get memory resource: %d\n", ret); return ret; } mipi_tx->regs_pa = mem->start; mipi_tx->cmdq_base = cmdq_register_device(dev); ref_clk = devm_clk_get(dev, NULL); if (IS_ERR(ref_clk)) { ret = PTR_ERR(ref_clk); dev_err(dev, "Failed to get reference clock: %d\n", ret); return ret; } ref_clk_name = __clk_get_name(ref_clk); ret = of_property_read_string(dev->of_node, "clock-output-names", &clk_init.name); if (ret < 0) { dev_err(dev, "Failed to read clock-output-names: %d\n", ret); return ret; } mtk_mipi_tx_pll_ops.prepare = mipi_tx->driver_data->pll_prepare; mtk_mipi_tx_pll_ops.unprepare = mipi_tx->driver_data->pll_unprepare; mipi_tx->pll_hw.init = &clk_init; mipi_tx->pll = devm_clk_register(dev, &mipi_tx->pll_hw); if (IS_ERR(mipi_tx->pll)) { ret = PTR_ERR(mipi_tx->pll); dev_err(dev, "Failed to register PLL: %d\n", ret); return ret; } phy = devm_phy_create(dev, NULL, &mtk_mipi_tx_ops); if (IS_ERR(phy)) { ret = PTR_ERR(phy); dev_err(dev, "Failed to create MIPI D-PHY: %d\n", ret); return ret; } phy_set_drvdata(phy, mipi_tx); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (IS_ERR(phy_provider)) { ret = PTR_ERR(phy_provider); return ret; } mipi_tx->dev = dev; #ifdef MTK_FILL_MIPI_IMPEDANCE backup_mipitx_impedance(mipi_tx); #endif DDPINFO("%s-\n", __func__); return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, mipi_tx->pll); } static int mtk_mipi_tx_remove(struct platform_device *pdev) { of_clk_del_provider(pdev->dev.of_node); return 0; } static const struct mtk_mipitx_data mt2701_mipitx_data = { .mppll_preserve = (3 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare, .pll_unprepare = mtk_mipi_tx_pll_unprepare, .power_on_signal = mtk_mipi_tx_power_on_signal, }; static const struct mtk_mipitx_data mt6779_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6779, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6779, }; static const struct mtk_mipitx_data mt6885_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6885, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6885, }; static const struct mtk_mipitx_data mt6885_mipitx_cphy_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_cphy_prepare_mt6885, .pll_unprepare = mtk_mipi_tx_pll_cphy_unprepare_mt6885, }; static const struct mtk_mipitx_data mt6873_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6873, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6873, }; static const struct mtk_mipitx_data mt6873_mipitx_cphy_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_cphy_prepare_mt6873, .pll_unprepare = mtk_mipi_tx_pll_cphy_unprepare_mt6873, }; static const struct mtk_mipitx_data mt6853_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6853, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6853, }; static const struct mtk_mipitx_data mt6877_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6877, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6877, }; static const struct mtk_mipitx_data mt6833_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6833, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6833, }; static const struct mtk_mipitx_data mt6833_mipitx_cphy_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_cphy_prepare_mt6873, .pll_unprepare = mtk_mipi_tx_pll_cphy_unprepare_mt6873, }; static const struct mtk_mipitx_data mt6781_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare_mt6781, .pll_unprepare = mtk_mipi_tx_pll_unprepare_mt6781, }; static const struct mtk_mipitx_data mt8173_mipitx_data = { .mppll_preserve = (0 << 8), .pll_prepare = mtk_mipi_tx_pll_prepare, .pll_unprepare = mtk_mipi_tx_pll_unprepare, .power_on_signal = mtk_mipi_tx_power_on_signal, }; static const struct of_device_id mtk_mipi_tx_match[] = { {.compatible = "mediatek,mt2701-mipi-tx", .data = &mt2701_mipitx_data}, {.compatible = "mediatek,mt6779-mipi-tx", .data = &mt6779_mipitx_data}, {.compatible = "mediatek,mt8173-mipi-tx", .data = &mt8173_mipitx_data}, {.compatible = "mediatek,mt6885-mipi-tx", .data = &mt6885_mipitx_data}, {.compatible = "mediatek,mt6873-mipi-tx", .data = &mt6873_mipitx_data}, {.compatible = "mediatek,mt6853-mipi-tx", .data = &mt6853_mipitx_data}, {.compatible = "mediatek,mt6877-mipi-tx", .data = &mt6877_mipitx_data}, {.compatible = "mediatek,mt6833-mipi-tx", .data = &mt6833_mipitx_data}, {.compatible = "mediatek,mt6781-mipi-tx", .data = &mt6781_mipitx_data}, {.compatible = "mediatek,mt6873-mipi-tx-cphy", .data = &mt6873_mipitx_cphy_data}, {.compatible = "mediatek,mt6885-mipi-tx-cphy", .data = &mt6885_mipitx_cphy_data}, {.compatible = "mediatek,mt6833-mipi-tx-cphy", .data = &mt6833_mipitx_cphy_data}, {}, }; struct platform_driver mtk_mipi_tx_driver = { .probe = mtk_mipi_tx_probe, .remove = mtk_mipi_tx_remove, .driver = { .name = "mediatek-mipi-tx", .of_match_table = mtk_mipi_tx_match, }, };