linux/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2018 MediaTek Inc.
   4 * Author: Chunhui Dai <chunhui.dai@mediatek.com>
   5 */
   6
   7#include "mtk_hdmi_phy.h"
   8
   9#define HDMI_CON0       0x00
  10#define RG_HDMITX_DRV_IBIAS             0
  11#define RG_HDMITX_DRV_IBIAS_MASK        (0x3f << 0)
  12#define RG_HDMITX_EN_SER                12
  13#define RG_HDMITX_EN_SER_MASK           (0x0f << 12)
  14#define RG_HDMITX_EN_SLDO               16
  15#define RG_HDMITX_EN_SLDO_MASK          (0x0f << 16)
  16#define RG_HDMITX_EN_PRED               20
  17#define RG_HDMITX_EN_PRED_MASK          (0x0f << 20)
  18#define RG_HDMITX_EN_IMP                24
  19#define RG_HDMITX_EN_IMP_MASK           (0x0f << 24)
  20#define RG_HDMITX_EN_DRV                28
  21#define RG_HDMITX_EN_DRV_MASK           (0x0f << 28)
  22
  23#define HDMI_CON1       0x04
  24#define RG_HDMITX_PRED_IBIAS            18
  25#define RG_HDMITX_PRED_IBIAS_MASK       (0x0f << 18)
  26#define RG_HDMITX_PRED_IMP              (0x01 << 22)
  27#define RG_HDMITX_DRV_IMP               26
  28#define RG_HDMITX_DRV_IMP_MASK          (0x3f << 26)
  29
  30#define HDMI_CON2       0x08
  31#define RG_HDMITX_EN_TX_CKLDO           (0x01 << 0)
  32#define RG_HDMITX_EN_TX_POSDIV          (0x01 << 1)
  33#define RG_HDMITX_TX_POSDIV             3
  34#define RG_HDMITX_TX_POSDIV_MASK        (0x03 << 3)
  35#define RG_HDMITX_EN_MBIAS              (0x01 << 6)
  36#define RG_HDMITX_MBIAS_LPF_EN          (0x01 << 7)
  37
  38#define HDMI_CON4       0x10
  39#define RG_HDMITX_RESERVE_MASK          (0xffffffff << 0)
  40
  41#define HDMI_CON6       0x18
  42#define RG_HTPLL_BR                     0
  43#define RG_HTPLL_BR_MASK                (0x03 << 0)
  44#define RG_HTPLL_BC                     2
  45#define RG_HTPLL_BC_MASK                (0x03 << 2)
  46#define RG_HTPLL_BP                     4
  47#define RG_HTPLL_BP_MASK                (0x0f << 4)
  48#define RG_HTPLL_IR                     8
  49#define RG_HTPLL_IR_MASK                (0x0f << 8)
  50#define RG_HTPLL_IC                     12
  51#define RG_HTPLL_IC_MASK                (0x0f << 12)
  52#define RG_HTPLL_POSDIV                 16
  53#define RG_HTPLL_POSDIV_MASK            (0x03 << 16)
  54#define RG_HTPLL_PREDIV                 18
  55#define RG_HTPLL_PREDIV_MASK            (0x03 << 18)
  56#define RG_HTPLL_FBKSEL                 20
  57#define RG_HTPLL_FBKSEL_MASK            (0x03 << 20)
  58#define RG_HTPLL_RLH_EN                 (0x01 << 22)
  59#define RG_HTPLL_FBKDIV                 24
  60#define RG_HTPLL_FBKDIV_MASK            (0x7f << 24)
  61#define RG_HTPLL_EN                     (0x01 << 31)
  62
  63#define HDMI_CON7       0x1c
  64#define RG_HTPLL_AUTOK_EN               (0x01 << 23)
  65#define RG_HTPLL_DIVEN                  28
  66#define RG_HTPLL_DIVEN_MASK             (0x07 << 28)
  67
  68static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
  69{
  70        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  71
  72        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
  73        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
  74        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
  75        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
  76        usleep_range(80, 100);
  77        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
  78        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
  79        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
  80        usleep_range(80, 100);
  81        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
  82        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
  83        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
  84        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
  85        usleep_range(80, 100);
  86        return 0;
  87}
  88
  89static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
  90{
  91        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  92
  93        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
  94        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
  95        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
  96        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
  97        usleep_range(80, 100);
  98        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
  99        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
 100        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
 101        usleep_range(80, 100);
 102        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
 103        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
 104        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
 105        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
 106        usleep_range(80, 100);
 107}
 108
 109static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 110                                    unsigned long *parent_rate)
 111{
 112        return rate;
 113}
 114
 115static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 116                                 unsigned long parent_rate)
 117{
 118        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 119        u32 pos_div;
 120
 121        if (rate <= 64000000)
 122                pos_div = 3;
 123        else if (rate <= 128000000)
 124                pos_div = 2;
 125        else
 126                pos_div = 1;
 127
 128        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
 129        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
 130        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
 131        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
 132                          RG_HTPLL_IC_MASK);
 133        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
 134                          RG_HTPLL_IR_MASK);
 135        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
 136                          RG_HDMITX_TX_POSDIV_MASK);
 137        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
 138                          RG_HTPLL_FBKSEL_MASK);
 139        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
 140                          RG_HTPLL_FBKDIV_MASK);
 141        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
 142                          RG_HTPLL_DIVEN_MASK);
 143        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
 144                          RG_HTPLL_BP_MASK);
 145        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
 146                          RG_HTPLL_BC_MASK);
 147        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
 148                          RG_HTPLL_BR_MASK);
 149
 150        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP);
 151        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
 152                          RG_HDMITX_PRED_IBIAS_MASK);
 153        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
 154        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
 155                          RG_HDMITX_DRV_IMP_MASK);
 156        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
 157        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
 158                          RG_HDMITX_DRV_IBIAS_MASK);
 159        return 0;
 160}
 161
 162static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
 163                                              unsigned long parent_rate)
 164{
 165        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 166        unsigned long out_rate, val;
 167
 168        val = (readl(hdmi_phy->regs + HDMI_CON6)
 169               & RG_HTPLL_PREDIV_MASK) >> RG_HTPLL_PREDIV;
 170        switch (val) {
 171        case 0x00:
 172                out_rate = parent_rate;
 173                break;
 174        case 0x01:
 175                out_rate = parent_rate / 2;
 176                break;
 177        default:
 178                out_rate = parent_rate / 4;
 179                break;
 180        }
 181
 182        val = (readl(hdmi_phy->regs + HDMI_CON6)
 183               & RG_HTPLL_FBKDIV_MASK) >> RG_HTPLL_FBKDIV;
 184        out_rate *= (val + 1) * 2;
 185        val = (readl(hdmi_phy->regs + HDMI_CON2)
 186               & RG_HDMITX_TX_POSDIV_MASK);
 187        out_rate >>= (val >> RG_HDMITX_TX_POSDIV);
 188
 189        if (readl(hdmi_phy->regs + HDMI_CON2) & RG_HDMITX_EN_TX_POSDIV)
 190                out_rate /= 5;
 191
 192        return out_rate;
 193}
 194
 195static const struct clk_ops mtk_hdmi_phy_pll_ops = {
 196        .prepare = mtk_hdmi_pll_prepare,
 197        .unprepare = mtk_hdmi_pll_unprepare,
 198        .set_rate = mtk_hdmi_pll_set_rate,
 199        .round_rate = mtk_hdmi_pll_round_rate,
 200        .recalc_rate = mtk_hdmi_pll_recalc_rate,
 201};
 202
 203static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
 204{
 205        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
 206        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
 207        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
 208        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
 209        usleep_range(80, 100);
 210        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
 211        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
 212        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
 213        usleep_range(80, 100);
 214        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
 215        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
 216        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
 217        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
 218        usleep_range(80, 100);
 219}
 220
 221static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
 222{
 223        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
 224        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
 225        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
 226        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
 227        usleep_range(80, 100);
 228        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
 229        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
 230        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
 231        usleep_range(80, 100);
 232        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
 233        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
 234        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
 235        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
 236        usleep_range(80, 100);
 237}
 238
 239struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
 240        .tz_disabled = true,
 241        .flags = CLK_SET_RATE_GATE,
 242        .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
 243        .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
 244        .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
 245};
 246
 247MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");
 248MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
 249MODULE_LICENSE("GPL v2");
 250