linux/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2014 MediaTek Inc.
   3 * Author: Jie Qiu <jie.qiu@mediatek.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 */
  14
  15#include <linux/clk.h>
  16#include <linux/clk-provider.h>
  17#include <linux/delay.h>
  18#include <linux/io.h>
  19#include <linux/mfd/syscon.h>
  20#include <linux/module.h>
  21#include <linux/phy/phy.h>
  22#include <linux/platform_device.h>
  23#include <linux/types.h>
  24
  25#define HDMI_CON0               0x00
  26#define RG_HDMITX_PLL_EN                BIT(31)
  27#define RG_HDMITX_PLL_FBKDIV            (0x7f << 24)
  28#define PLL_FBKDIV_SHIFT                24
  29#define RG_HDMITX_PLL_FBKSEL            (0x3 << 22)
  30#define PLL_FBKSEL_SHIFT                22
  31#define RG_HDMITX_PLL_PREDIV            (0x3 << 20)
  32#define PREDIV_SHIFT                    20
  33#define RG_HDMITX_PLL_POSDIV            (0x3 << 18)
  34#define POSDIV_SHIFT                    18
  35#define RG_HDMITX_PLL_RST_DLY           (0x3 << 16)
  36#define RG_HDMITX_PLL_IR                (0xf << 12)
  37#define PLL_IR_SHIFT                    12
  38#define RG_HDMITX_PLL_IC                (0xf << 8)
  39#define PLL_IC_SHIFT                    8
  40#define RG_HDMITX_PLL_BP                (0xf << 4)
  41#define PLL_BP_SHIFT                    4
  42#define RG_HDMITX_PLL_BR                (0x3 << 2)
  43#define PLL_BR_SHIFT                    2
  44#define RG_HDMITX_PLL_BC                (0x3 << 0)
  45#define PLL_BC_SHIFT                    0
  46#define HDMI_CON1               0x04
  47#define RG_HDMITX_PLL_DIVEN             (0x7 << 29)
  48#define PLL_DIVEN_SHIFT                 29
  49#define RG_HDMITX_PLL_AUTOK_EN          BIT(28)
  50#define RG_HDMITX_PLL_AUTOK_KF          (0x3 << 26)
  51#define RG_HDMITX_PLL_AUTOK_KS          (0x3 << 24)
  52#define RG_HDMITX_PLL_AUTOK_LOAD        BIT(23)
  53#define RG_HDMITX_PLL_BAND              (0x3f << 16)
  54#define RG_HDMITX_PLL_REF_SEL           BIT(15)
  55#define RG_HDMITX_PLL_BIAS_EN           BIT(14)
  56#define RG_HDMITX_PLL_BIAS_LPF_EN       BIT(13)
  57#define RG_HDMITX_PLL_TXDIV_EN          BIT(12)
  58#define RG_HDMITX_PLL_TXDIV             (0x3 << 10)
  59#define PLL_TXDIV_SHIFT                 10
  60#define RG_HDMITX_PLL_LVROD_EN          BIT(9)
  61#define RG_HDMITX_PLL_MONVC_EN          BIT(8)
  62#define RG_HDMITX_PLL_MONCK_EN          BIT(7)
  63#define RG_HDMITX_PLL_MONREF_EN         BIT(6)
  64#define RG_HDMITX_PLL_TST_EN            BIT(5)
  65#define RG_HDMITX_PLL_TST_CK_EN         BIT(4)
  66#define RG_HDMITX_PLL_TST_SEL           (0xf << 0)
  67#define HDMI_CON2               0x08
  68#define RGS_HDMITX_PLL_AUTOK_BAND       (0x7f << 8)
  69#define RGS_HDMITX_PLL_AUTOK_FAIL       BIT(1)
  70#define RG_HDMITX_EN_TX_CKLDO           BIT(0)
  71#define HDMI_CON3               0x0c
  72#define RG_HDMITX_SER_EN                (0xf << 28)
  73#define RG_HDMITX_PRD_EN                (0xf << 24)
  74#define RG_HDMITX_PRD_IMP_EN            (0xf << 20)
  75#define RG_HDMITX_DRV_EN                (0xf << 16)
  76#define RG_HDMITX_DRV_IMP_EN            (0xf << 12)
  77#define DRV_IMP_EN_SHIFT                12
  78#define RG_HDMITX_MHLCK_FORCE           BIT(10)
  79#define RG_HDMITX_MHLCK_PPIX_EN         BIT(9)
  80#define RG_HDMITX_MHLCK_EN              BIT(8)
  81#define RG_HDMITX_SER_DIN_SEL           (0xf << 4)
  82#define RG_HDMITX_SER_5T1_BIST_EN       BIT(3)
  83#define RG_HDMITX_SER_BIST_TOG          BIT(2)
  84#define RG_HDMITX_SER_DIN_TOG           BIT(1)
  85#define RG_HDMITX_SER_CLKDIG_INV        BIT(0)
  86#define HDMI_CON4               0x10
  87#define RG_HDMITX_PRD_IBIAS_CLK         (0xf << 24)
  88#define RG_HDMITX_PRD_IBIAS_D2          (0xf << 16)
  89#define RG_HDMITX_PRD_IBIAS_D1          (0xf << 8)
  90#define RG_HDMITX_PRD_IBIAS_D0          (0xf << 0)
  91#define PRD_IBIAS_CLK_SHIFT             24
  92#define PRD_IBIAS_D2_SHIFT              16
  93#define PRD_IBIAS_D1_SHIFT              8
  94#define PRD_IBIAS_D0_SHIFT              0
  95#define HDMI_CON5               0x14
  96#define RG_HDMITX_DRV_IBIAS_CLK         (0x3f << 24)
  97#define RG_HDMITX_DRV_IBIAS_D2          (0x3f << 16)
  98#define RG_HDMITX_DRV_IBIAS_D1          (0x3f << 8)
  99#define RG_HDMITX_DRV_IBIAS_D0          (0x3f << 0)
 100#define DRV_IBIAS_CLK_SHIFT             24
 101#define DRV_IBIAS_D2_SHIFT              16
 102#define DRV_IBIAS_D1_SHIFT              8
 103#define DRV_IBIAS_D0_SHIFT              0
 104#define HDMI_CON6               0x18
 105#define RG_HDMITX_DRV_IMP_CLK           (0x3f << 24)
 106#define RG_HDMITX_DRV_IMP_D2            (0x3f << 16)
 107#define RG_HDMITX_DRV_IMP_D1            (0x3f << 8)
 108#define RG_HDMITX_DRV_IMP_D0            (0x3f << 0)
 109#define DRV_IMP_CLK_SHIFT               24
 110#define DRV_IMP_D2_SHIFT                16
 111#define DRV_IMP_D1_SHIFT                8
 112#define DRV_IMP_D0_SHIFT                0
 113#define HDMI_CON7               0x1c
 114#define RG_HDMITX_MHLCK_DRV_IBIAS       (0x1f << 27)
 115#define RG_HDMITX_SER_DIN               (0x3ff << 16)
 116#define RG_HDMITX_CHLDC_TST             (0xf << 12)
 117#define RG_HDMITX_CHLCK_TST             (0xf << 8)
 118#define RG_HDMITX_RESERVE               (0xff << 0)
 119#define HDMI_CON8               0x20
 120#define RGS_HDMITX_2T1_LEV              (0xf << 16)
 121#define RGS_HDMITX_2T1_EDG              (0xf << 12)
 122#define RGS_HDMITX_5T1_LEV              (0xf << 8)
 123#define RGS_HDMITX_5T1_EDG              (0xf << 4)
 124#define RGS_HDMITX_PLUG_TST             BIT(0)
 125
 126struct mtk_hdmi_phy {
 127        void __iomem *regs;
 128        struct device *dev;
 129        struct clk *pll;
 130        struct clk_hw pll_hw;
 131        unsigned long pll_rate;
 132        u8 drv_imp_clk;
 133        u8 drv_imp_d2;
 134        u8 drv_imp_d1;
 135        u8 drv_imp_d0;
 136        u32 ibias;
 137        u32 ibias_up;
 138};
 139
 140static const u8 PREDIV[3][4] = {
 141        {0x0, 0x0, 0x0, 0x0},   /* 27Mhz */
 142        {0x1, 0x1, 0x1, 0x1},   /* 74Mhz */
 143        {0x1, 0x1, 0x1, 0x1}    /* 148Mhz */
 144};
 145
 146static const u8 TXDIV[3][4] = {
 147        {0x3, 0x3, 0x3, 0x2},   /* 27Mhz */
 148        {0x2, 0x1, 0x1, 0x1},   /* 74Mhz */
 149        {0x1, 0x0, 0x0, 0x0}    /* 148Mhz */
 150};
 151
 152static const u8 FBKSEL[3][4] = {
 153        {0x1, 0x1, 0x1, 0x1},   /* 27Mhz */
 154        {0x1, 0x0, 0x1, 0x1},   /* 74Mhz */
 155        {0x1, 0x0, 0x1, 0x1}    /* 148Mhz */
 156};
 157
 158static const u8 FBKDIV[3][4] = {
 159        {19, 24, 29, 19},       /* 27Mhz */
 160        {19, 24, 14, 19},       /* 74Mhz */
 161        {19, 24, 14, 19}        /* 148Mhz */
 162};
 163
 164static const u8 DIVEN[3][4] = {
 165        {0x2, 0x1, 0x1, 0x2},   /* 27Mhz */
 166        {0x2, 0x2, 0x2, 0x2},   /* 74Mhz */
 167        {0x2, 0x2, 0x2, 0x2}    /* 148Mhz */
 168};
 169
 170static const u8 HTPLLBP[3][4] = {
 171        {0xc, 0xc, 0x8, 0xc},   /* 27Mhz */
 172        {0xc, 0xf, 0xf, 0xc},   /* 74Mhz */
 173        {0xc, 0xf, 0xf, 0xc}    /* 148Mhz */
 174};
 175
 176static const u8 HTPLLBC[3][4] = {
 177        {0x2, 0x3, 0x3, 0x2},   /* 27Mhz */
 178        {0x2, 0x3, 0x3, 0x2},   /* 74Mhz */
 179        {0x2, 0x3, 0x3, 0x2}    /* 148Mhz */
 180};
 181
 182static const u8 HTPLLBR[3][4] = {
 183        {0x1, 0x1, 0x0, 0x1},   /* 27Mhz */
 184        {0x1, 0x2, 0x2, 0x1},   /* 74Mhz */
 185        {0x1, 0x2, 0x2, 0x1}    /* 148Mhz */
 186};
 187
 188static void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
 189                                    u32 bits)
 190{
 191        void __iomem *reg = hdmi_phy->regs + offset;
 192        u32 tmp;
 193
 194        tmp = readl(reg);
 195        tmp &= ~bits;
 196        writel(tmp, reg);
 197}
 198
 199static void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
 200                                  u32 bits)
 201{
 202        void __iomem *reg = hdmi_phy->regs + offset;
 203        u32 tmp;
 204
 205        tmp = readl(reg);
 206        tmp |= bits;
 207        writel(tmp, reg);
 208}
 209
 210static void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
 211                              u32 val, u32 mask)
 212{
 213        void __iomem *reg = hdmi_phy->regs + offset;
 214        u32 tmp;
 215
 216        tmp = readl(reg);
 217        tmp = (tmp & ~mask) | (val & mask);
 218        writel(tmp, reg);
 219}
 220
 221static inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
 222{
 223        return container_of(hw, struct mtk_hdmi_phy, pll_hw);
 224}
 225
 226static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
 227{
 228        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 229
 230        dev_dbg(hdmi_phy->dev, "%s\n", __func__);
 231
 232        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
 233        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
 234        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_MHLCK_EN);
 235        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
 236        usleep_range(100, 150);
 237        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
 238        usleep_range(100, 150);
 239        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
 240        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
 241
 242        return 0;
 243}
 244
 245static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
 246{
 247        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 248
 249        dev_dbg(hdmi_phy->dev, "%s\n", __func__);
 250
 251        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
 252        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
 253        usleep_range(100, 150);
 254        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
 255        usleep_range(100, 150);
 256        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
 257        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
 258        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
 259        usleep_range(100, 150);
 260}
 261
 262static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 263                                 unsigned long parent_rate)
 264{
 265        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 266        unsigned int pre_div;
 267        unsigned int div;
 268        unsigned int pre_ibias;
 269        unsigned int hdmi_ibias;
 270        unsigned int imp_en;
 271
 272        dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__,
 273                rate, parent_rate);
 274
 275        if (rate <= 27000000) {
 276                pre_div = 0;
 277                div = 3;
 278        } else if (rate <= 74250000) {
 279                pre_div = 1;
 280                div = 2;
 281        } else {
 282                pre_div = 1;
 283                div = 1;
 284        }
 285
 286        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
 287                          (pre_div << PREDIV_SHIFT), RG_HDMITX_PLL_PREDIV);
 288        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
 289        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
 290                          (0x1 << PLL_IC_SHIFT) | (0x1 << PLL_IR_SHIFT),
 291                          RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR);
 292        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
 293                          (div << PLL_TXDIV_SHIFT), RG_HDMITX_PLL_TXDIV);
 294        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
 295                          (0x1 << PLL_FBKSEL_SHIFT) | (19 << PLL_FBKDIV_SHIFT),
 296                          RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV);
 297        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
 298                          (0x2 << PLL_DIVEN_SHIFT), RG_HDMITX_PLL_DIVEN);
 299        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
 300                          (0xc << PLL_BP_SHIFT) | (0x2 << PLL_BC_SHIFT) |
 301                          (0x1 << PLL_BR_SHIFT),
 302                          RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
 303                          RG_HDMITX_PLL_BR);
 304        if (rate < 165000000) {
 305                mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
 306                                        RG_HDMITX_PRD_IMP_EN);
 307                pre_ibias = 0x3;
 308                imp_en = 0x0;
 309                hdmi_ibias = hdmi_phy->ibias;
 310        } else {
 311                mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
 312                                      RG_HDMITX_PRD_IMP_EN);
 313                pre_ibias = 0x6;
 314                imp_en = 0xf;
 315                hdmi_ibias = hdmi_phy->ibias_up;
 316        }
 317        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
 318                          (pre_ibias << PRD_IBIAS_CLK_SHIFT) |
 319                          (pre_ibias << PRD_IBIAS_D2_SHIFT) |
 320                          (pre_ibias << PRD_IBIAS_D1_SHIFT) |
 321                          (pre_ibias << PRD_IBIAS_D0_SHIFT),
 322                          RG_HDMITX_PRD_IBIAS_CLK |
 323                          RG_HDMITX_PRD_IBIAS_D2 |
 324                          RG_HDMITX_PRD_IBIAS_D1 |
 325                          RG_HDMITX_PRD_IBIAS_D0);
 326        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
 327                          (imp_en << DRV_IMP_EN_SHIFT),
 328                          RG_HDMITX_DRV_IMP_EN);
 329        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
 330                          (hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
 331                          (hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
 332                          (hdmi_phy->drv_imp_d1 << DRV_IMP_D1_SHIFT) |
 333                          (hdmi_phy->drv_imp_d0 << DRV_IMP_D0_SHIFT),
 334                          RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
 335                          RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
 336        mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
 337                          (hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
 338                          (hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
 339                          (hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
 340                          (hdmi_ibias << DRV_IBIAS_D0_SHIFT),
 341                          RG_HDMITX_DRV_IBIAS_CLK |
 342                          RG_HDMITX_DRV_IBIAS_D2 |
 343                          RG_HDMITX_DRV_IBIAS_D1 |
 344                          RG_HDMITX_DRV_IBIAS_D0);
 345        return 0;
 346}
 347
 348static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 349                                    unsigned long *parent_rate)
 350{
 351        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 352
 353        hdmi_phy->pll_rate = rate;
 354        if (rate <= 74250000)
 355                *parent_rate = rate;
 356        else
 357                *parent_rate = rate / 2;
 358
 359        return rate;
 360}
 361
 362static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
 363                                              unsigned long parent_rate)
 364{
 365        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 366
 367        return hdmi_phy->pll_rate;
 368}
 369
 370static const struct clk_ops mtk_hdmi_pll_ops = {
 371        .prepare = mtk_hdmi_pll_prepare,
 372        .unprepare = mtk_hdmi_pll_unprepare,
 373        .set_rate = mtk_hdmi_pll_set_rate,
 374        .round_rate = mtk_hdmi_pll_round_rate,
 375        .recalc_rate = mtk_hdmi_pll_recalc_rate,
 376};
 377
 378static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
 379{
 380        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
 381                              RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
 382                              RG_HDMITX_DRV_EN);
 383        usleep_range(100, 150);
 384}
 385
 386static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
 387{
 388        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
 389                                RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
 390                                RG_HDMITX_SER_EN);
 391}
 392
 393static int mtk_hdmi_phy_power_on(struct phy *phy)
 394{
 395        struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
 396        int ret;
 397
 398        ret = clk_prepare_enable(hdmi_phy->pll);
 399        if (ret < 0)
 400                return ret;
 401
 402        mtk_hdmi_phy_enable_tmds(hdmi_phy);
 403
 404        return 0;
 405}
 406
 407static int mtk_hdmi_phy_power_off(struct phy *phy)
 408{
 409        struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
 410
 411        mtk_hdmi_phy_disable_tmds(hdmi_phy);
 412        clk_disable_unprepare(hdmi_phy->pll);
 413
 414        return 0;
 415}
 416
 417static const struct phy_ops mtk_hdmi_phy_ops = {
 418        .power_on = mtk_hdmi_phy_power_on,
 419        .power_off = mtk_hdmi_phy_power_off,
 420        .owner = THIS_MODULE,
 421};
 422
 423static int mtk_hdmi_phy_probe(struct platform_device *pdev)
 424{
 425        struct device *dev = &pdev->dev;
 426        struct mtk_hdmi_phy *hdmi_phy;
 427        struct resource *mem;
 428        struct clk *ref_clk;
 429        const char *ref_clk_name;
 430        struct clk_init_data clk_init = {
 431                .ops = &mtk_hdmi_pll_ops,
 432                .num_parents = 1,
 433                .parent_names = (const char * const *)&ref_clk_name,
 434                .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
 435        };
 436        struct phy *phy;
 437        struct phy_provider *phy_provider;
 438        int ret;
 439
 440        hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
 441        if (!hdmi_phy)
 442                return -ENOMEM;
 443
 444        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 445        hdmi_phy->regs = devm_ioremap_resource(dev, mem);
 446        if (IS_ERR(hdmi_phy->regs)) {
 447                ret = PTR_ERR(hdmi_phy->regs);
 448                dev_err(dev, "Failed to get memory resource: %d\n", ret);
 449                return ret;
 450        }
 451
 452        ref_clk = devm_clk_get(dev, "pll_ref");
 453        if (IS_ERR(ref_clk)) {
 454                ret = PTR_ERR(ref_clk);
 455                dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
 456                        ret);
 457                return ret;
 458        }
 459        ref_clk_name = __clk_get_name(ref_clk);
 460
 461        ret = of_property_read_string(dev->of_node, "clock-output-names",
 462                                      &clk_init.name);
 463        if (ret < 0) {
 464                dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
 465                return ret;
 466        }
 467
 468        hdmi_phy->pll_hw.init = &clk_init;
 469        hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
 470        if (IS_ERR(hdmi_phy->pll)) {
 471                ret = PTR_ERR(hdmi_phy->pll);
 472                dev_err(dev, "Failed to register PLL: %d\n", ret);
 473                return ret;
 474        }
 475
 476        ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
 477                                   &hdmi_phy->ibias);
 478        if (ret < 0) {
 479                dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
 480                return ret;
 481        }
 482
 483        ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
 484                                   &hdmi_phy->ibias_up);
 485        if (ret < 0) {
 486                dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
 487                return ret;
 488        }
 489
 490        dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
 491        hdmi_phy->drv_imp_clk = 0x30;
 492        hdmi_phy->drv_imp_d2 = 0x30;
 493        hdmi_phy->drv_imp_d1 = 0x30;
 494        hdmi_phy->drv_imp_d0 = 0x30;
 495
 496        phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops);
 497        if (IS_ERR(phy)) {
 498                dev_err(dev, "Failed to create HDMI PHY\n");
 499                return PTR_ERR(phy);
 500        }
 501        phy_set_drvdata(phy, hdmi_phy);
 502
 503        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 504        if (IS_ERR(phy_provider))
 505                return PTR_ERR(phy_provider);
 506
 507        hdmi_phy->dev = dev;
 508        return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
 509                                   hdmi_phy->pll);
 510}
 511
 512static int mtk_hdmi_phy_remove(struct platform_device *pdev)
 513{
 514        return 0;
 515}
 516
 517static const struct of_device_id mtk_hdmi_phy_match[] = {
 518        { .compatible = "mediatek,mt8173-hdmi-phy", },
 519        {},
 520};
 521
 522struct platform_driver mtk_hdmi_phy_driver = {
 523        .probe = mtk_hdmi_phy_probe,
 524        .remove = mtk_hdmi_phy_remove,
 525        .driver = {
 526                .name = "mediatek-hdmi-phy",
 527                .of_match_table = mtk_hdmi_phy_match,
 528        },
 529};
 530
 531MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
 532MODULE_DESCRIPTION("MediaTek MT8173 HDMI PHY Driver");
 533MODULE_LICENSE("GPL v2");
 534