6db4831e98
Android 14
2563 lines
72 KiB
C
2563 lines
72 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/io.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/phy/phy.h>
|
|
#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,
|
|
},
|
|
};
|