phy: mediatek: Move mtk_hdmi_phy driver into drivers/phy/mediatek folder
authorCK Hu <ck.hu@mediatek.com>
Mon, 13 May 2019 02:22:25 +0000 (10:22 +0800)
committerChun-Kuang Hu <chunkuang.hu@kernel.org>
Sat, 5 Sep 2020 23:03:21 +0000 (07:03 +0800)
mtk_hdmi_phy is currently placed inside mediatek drm driver, but it's
more suitable to place a phy driver into phy driver folder, so move
mtk_hdmi_phy driver into phy driver folder.

Signed-off-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Acked-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Tested-by: Frank Wunderlich <frank-w@public-files.de>
12 files changed:
drivers/gpu/drm/mediatek/Kconfig
drivers/gpu/drm/mediatek/Makefile
drivers/gpu/drm/mediatek/mtk_hdmi_phy.c [deleted file]
drivers/gpu/drm/mediatek/mtk_hdmi_phy.h [deleted file]
drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c [deleted file]
drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c [deleted file]
drivers/phy/mediatek/Kconfig
drivers/phy/mediatek/Makefile
drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c [new file with mode: 0644]
drivers/phy/mediatek/phy-mtk-hdmi-mt8173.c [new file with mode: 0644]
drivers/phy/mediatek/phy-mtk-hdmi.c [new file with mode: 0644]
drivers/phy/mediatek/phy-mtk-hdmi.h [new file with mode: 0644]

index 6363f2c..65cd03a 100644 (file)
@@ -27,10 +27,3 @@ config DRM_MEDIATEK_HDMI
        select PHY_MTK_HDMI
        help
          DRM/KMS HDMI driver for Mediatek SoCs
-
-config PHY_MTK_HDMI
-       tristate "MediaTek HDMI-PHY Driver"
-       depends on ARCH_MEDIATEK && OF
-       select GENERIC_PHY
-       help
-         Support HDMI PHY for Mediatek SoCs.
index fcbef23..77b0fd8 100644 (file)
@@ -22,9 +22,3 @@ mediatek-drm-hdmi-objs := mtk_cec.o \
                          mtk_hdmi_ddc.o
 
 obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o
-
-phy-mtk-hdmi-drv-objs := mtk_hdmi_phy.o \
-                        mtk_mt2701_hdmi_phy.o \
-                        mtk_mt8173_hdmi_phy.o
-
-obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
deleted file mode 100644 (file)
index fe022ac..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2018 MediaTek Inc.
- * Author: Jie Qiu <jie.qiu@mediatek.com>
- */
-
-#include "mtk_hdmi_phy.h"
-
-static int mtk_hdmi_phy_power_on(struct phy *phy);
-static int mtk_hdmi_phy_power_off(struct phy *phy);
-
-static const struct phy_ops mtk_hdmi_phy_dev_ops = {
-       .power_on = mtk_hdmi_phy_power_on,
-       .power_off = mtk_hdmi_phy_power_off,
-       .owner = THIS_MODULE,
-};
-
-void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
-                            u32 bits)
-{
-       void __iomem *reg = hdmi_phy->regs + offset;
-       u32 tmp;
-
-       tmp = readl(reg);
-       tmp &= ~bits;
-       writel(tmp, reg);
-}
-
-void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
-                          u32 bits)
-{
-       void __iomem *reg = hdmi_phy->regs + offset;
-       u32 tmp;
-
-       tmp = readl(reg);
-       tmp |= bits;
-       writel(tmp, reg);
-}
-
-void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
-                      u32 val, u32 mask)
-{
-       void __iomem *reg = hdmi_phy->regs + offset;
-       u32 tmp;
-
-       tmp = readl(reg);
-       tmp = (tmp & ~mask) | (val & mask);
-       writel(tmp, reg);
-}
-
-inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
-{
-       return container_of(hw, struct mtk_hdmi_phy, pll_hw);
-}
-
-static int mtk_hdmi_phy_power_on(struct phy *phy)
-{
-       struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
-       int ret;
-
-       ret = clk_prepare_enable(hdmi_phy->pll);
-       if (ret < 0)
-               return ret;
-
-       hdmi_phy->conf->hdmi_phy_enable_tmds(hdmi_phy);
-       return 0;
-}
-
-static int mtk_hdmi_phy_power_off(struct phy *phy)
-{
-       struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
-
-       hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
-       clk_disable_unprepare(hdmi_phy->pll);
-
-       return 0;
-}
-
-static const struct phy_ops *
-mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
-{
-       if (hdmi_phy && hdmi_phy->conf &&
-           hdmi_phy->conf->hdmi_phy_enable_tmds &&
-           hdmi_phy->conf->hdmi_phy_disable_tmds)
-               return &mtk_hdmi_phy_dev_ops;
-
-       dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
-               return NULL;
-}
-
-static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
-                                     struct clk_init_data *clk_init)
-{
-       clk_init->flags = hdmi_phy->conf->flags;
-       clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops;
-}
-
-static int mtk_hdmi_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct mtk_hdmi_phy *hdmi_phy;
-       struct resource *mem;
-       struct clk *ref_clk;
-       const char *ref_clk_name;
-       struct clk_init_data clk_init = {
-               .num_parents = 1,
-               .parent_names = (const char * const *)&ref_clk_name,
-       };
-
-       struct phy *phy;
-       struct phy_provider *phy_provider;
-       int ret;
-
-       hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
-       if (!hdmi_phy)
-               return -ENOMEM;
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hdmi_phy->regs = devm_ioremap_resource(dev, mem);
-       if (IS_ERR(hdmi_phy->regs)) {
-               ret = PTR_ERR(hdmi_phy->regs);
-               dev_err(dev, "Failed to get memory resource: %d\n", ret);
-               return ret;
-       }
-
-       ref_clk = devm_clk_get(dev, "pll_ref");
-       if (IS_ERR(ref_clk)) {
-               ret = PTR_ERR(ref_clk);
-               dev_err(&pdev->dev, "Failed to get PLL 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;
-       }
-
-       hdmi_phy->dev = dev;
-       hdmi_phy->conf =
-               (struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
-       mtk_hdmi_phy_clk_get_data(hdmi_phy, &clk_init);
-       hdmi_phy->pll_hw.init = &clk_init;
-       hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
-       if (IS_ERR(hdmi_phy->pll)) {
-               ret = PTR_ERR(hdmi_phy->pll);
-               dev_err(dev, "Failed to register PLL: %d\n", ret);
-               return ret;
-       }
-
-       ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
-                                  &hdmi_phy->ibias);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
-               return ret;
-       }
-
-       ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
-                                  &hdmi_phy->ibias_up);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
-               return ret;
-       }
-
-       dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
-       hdmi_phy->drv_imp_clk = 0x30;
-       hdmi_phy->drv_imp_d2 = 0x30;
-       hdmi_phy->drv_imp_d1 = 0x30;
-       hdmi_phy->drv_imp_d0 = 0x30;
-
-       phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy));
-       if (IS_ERR(phy)) {
-               dev_err(dev, "Failed to create HDMI PHY\n");
-               return PTR_ERR(phy);
-       }
-       phy_set_drvdata(phy, hdmi_phy);
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               dev_err(dev, "Failed to register HDMI PHY\n");
-               return PTR_ERR(phy_provider);
-       }
-
-       return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
-                                  hdmi_phy->pll);
-}
-
-static const struct of_device_id mtk_hdmi_phy_match[] = {
-       { .compatible = "mediatek,mt2701-hdmi-phy",
-         .data = &mtk_hdmi_phy_2701_conf,
-       },
-       { .compatible = "mediatek,mt8173-hdmi-phy",
-         .data = &mtk_hdmi_phy_8173_conf,
-       },
-       {},
-};
-
-struct platform_driver mtk_hdmi_phy_driver = {
-       .probe = mtk_hdmi_phy_probe,
-       .driver = {
-               .name = "mediatek-hdmi-phy",
-               .of_match_table = mtk_hdmi_phy_match,
-       },
-};
-module_platform_driver(mtk_hdmi_phy_driver);
-
-MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h
deleted file mode 100644 (file)
index b13e1d5..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2018 MediaTek Inc.
- * Author: Chunhui Dai <chunhui.dai@mediatek.com>
- */
-
-#ifndef _MTK_HDMI_PHY_H
-#define _MTK_HDMI_PHY_H
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-
-struct mtk_hdmi_phy;
-
-struct mtk_hdmi_phy_conf {
-       unsigned long flags;
-       const struct clk_ops *hdmi_phy_clk_ops;
-       void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
-       void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
-};
-
-struct mtk_hdmi_phy {
-       void __iomem *regs;
-       struct device *dev;
-       struct mtk_hdmi_phy_conf *conf;
-       struct clk *pll;
-       struct clk_hw pll_hw;
-       unsigned long pll_rate;
-       unsigned char drv_imp_clk;
-       unsigned char drv_imp_d2;
-       unsigned char drv_imp_d1;
-       unsigned char drv_imp_d0;
-       unsigned int ibias;
-       unsigned int ibias_up;
-};
-
-void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
-                            u32 bits);
-void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
-                          u32 bits);
-void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
-                      u32 val, u32 mask);
-struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
-
-extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
-extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf;
-
-#endif /* _MTK_HDMI_PHY_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
deleted file mode 100644 (file)
index 99fe05c..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2018 MediaTek Inc.
- * Author: Chunhui Dai <chunhui.dai@mediatek.com>
- */
-
-#include "mtk_hdmi_phy.h"
-
-#define HDMI_CON0      0x00
-#define RG_HDMITX_DRV_IBIAS            0
-#define RG_HDMITX_DRV_IBIAS_MASK       (0x3f << 0)
-#define RG_HDMITX_EN_SER               12
-#define RG_HDMITX_EN_SER_MASK          (0x0f << 12)
-#define RG_HDMITX_EN_SLDO              16
-#define RG_HDMITX_EN_SLDO_MASK         (0x0f << 16)
-#define RG_HDMITX_EN_PRED              20
-#define RG_HDMITX_EN_PRED_MASK         (0x0f << 20)
-#define RG_HDMITX_EN_IMP               24
-#define RG_HDMITX_EN_IMP_MASK          (0x0f << 24)
-#define RG_HDMITX_EN_DRV               28
-#define RG_HDMITX_EN_DRV_MASK          (0x0f << 28)
-
-#define HDMI_CON1      0x04
-#define RG_HDMITX_PRED_IBIAS           18
-#define RG_HDMITX_PRED_IBIAS_MASK      (0x0f << 18)
-#define RG_HDMITX_PRED_IMP             (0x01 << 22)
-#define RG_HDMITX_DRV_IMP              26
-#define RG_HDMITX_DRV_IMP_MASK         (0x3f << 26)
-
-#define HDMI_CON2      0x08
-#define RG_HDMITX_EN_TX_CKLDO          (0x01 << 0)
-#define RG_HDMITX_EN_TX_POSDIV         (0x01 << 1)
-#define RG_HDMITX_TX_POSDIV            3
-#define RG_HDMITX_TX_POSDIV_MASK       (0x03 << 3)
-#define RG_HDMITX_EN_MBIAS             (0x01 << 6)
-#define RG_HDMITX_MBIAS_LPF_EN         (0x01 << 7)
-
-#define HDMI_CON4      0x10
-#define RG_HDMITX_RESERVE_MASK         (0xffffffff << 0)
-
-#define HDMI_CON6      0x18
-#define RG_HTPLL_BR                    0
-#define RG_HTPLL_BR_MASK               (0x03 << 0)
-#define RG_HTPLL_BC                    2
-#define RG_HTPLL_BC_MASK               (0x03 << 2)
-#define RG_HTPLL_BP                    4
-#define RG_HTPLL_BP_MASK               (0x0f << 4)
-#define RG_HTPLL_IR                    8
-#define RG_HTPLL_IR_MASK               (0x0f << 8)
-#define RG_HTPLL_IC                    12
-#define RG_HTPLL_IC_MASK               (0x0f << 12)
-#define RG_HTPLL_POSDIV                        16
-#define RG_HTPLL_POSDIV_MASK           (0x03 << 16)
-#define RG_HTPLL_PREDIV                        18
-#define RG_HTPLL_PREDIV_MASK           (0x03 << 18)
-#define RG_HTPLL_FBKSEL                        20
-#define RG_HTPLL_FBKSEL_MASK           (0x03 << 20)
-#define RG_HTPLL_RLH_EN                        (0x01 << 22)
-#define RG_HTPLL_FBKDIV                        24
-#define RG_HTPLL_FBKDIV_MASK           (0x7f << 24)
-#define RG_HTPLL_EN                    (0x01 << 31)
-
-#define HDMI_CON7      0x1c
-#define RG_HTPLL_AUTOK_EN              (0x01 << 23)
-#define RG_HTPLL_DIVEN                 28
-#define RG_HTPLL_DIVEN_MASK            (0x07 << 28)
-
-static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
-       usleep_range(80, 100);
-       return 0;
-}
-
-static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
-       usleep_range(80, 100);
-}
-
-static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                   unsigned long *parent_rate)
-{
-       return rate;
-}
-
-static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long parent_rate)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-       u32 pos_div;
-
-       if (rate <= 64000000)
-               pos_div = 3;
-       else if (rate <= 128000000)
-               pos_div = 2;
-       else
-               pos_div = 1;
-
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
-                         RG_HTPLL_IC_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
-                         RG_HTPLL_IR_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
-                         RG_HDMITX_TX_POSDIV_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
-                         RG_HTPLL_FBKSEL_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
-                         RG_HTPLL_FBKDIV_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
-                         RG_HTPLL_DIVEN_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
-                         RG_HTPLL_BP_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
-                         RG_HTPLL_BC_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
-                         RG_HTPLL_BR_MASK);
-
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
-                         RG_HDMITX_PRED_IBIAS_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
-                         RG_HDMITX_DRV_IMP_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
-                         RG_HDMITX_DRV_IBIAS_MASK);
-       return 0;
-}
-
-static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
-                                             unsigned long parent_rate)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-       unsigned long out_rate, val;
-
-       val = (readl(hdmi_phy->regs + HDMI_CON6)
-              & RG_HTPLL_PREDIV_MASK) >> RG_HTPLL_PREDIV;
-       switch (val) {
-       case 0x00:
-               out_rate = parent_rate;
-               break;
-       case 0x01:
-               out_rate = parent_rate / 2;
-               break;
-       default:
-               out_rate = parent_rate / 4;
-               break;
-       }
-
-       val = (readl(hdmi_phy->regs + HDMI_CON6)
-              & RG_HTPLL_FBKDIV_MASK) >> RG_HTPLL_FBKDIV;
-       out_rate *= (val + 1) * 2;
-       val = (readl(hdmi_phy->regs + HDMI_CON2)
-              & RG_HDMITX_TX_POSDIV_MASK);
-       out_rate >>= (val >> RG_HDMITX_TX_POSDIV);
-
-       if (readl(hdmi_phy->regs + HDMI_CON2) & RG_HDMITX_EN_TX_POSDIV)
-               out_rate /= 5;
-
-       return out_rate;
-}
-
-static const struct clk_ops mtk_hdmi_phy_pll_ops = {
-       .prepare = mtk_hdmi_pll_prepare,
-       .unprepare = mtk_hdmi_pll_unprepare,
-       .set_rate = mtk_hdmi_pll_set_rate,
-       .round_rate = mtk_hdmi_pll_round_rate,
-       .recalc_rate = mtk_hdmi_pll_recalc_rate,
-};
-
-static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
-{
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
-       usleep_range(80, 100);
-}
-
-static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
-{
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
-       usleep_range(80, 100);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
-       usleep_range(80, 100);
-}
-
-struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
-       .flags = CLK_SET_RATE_GATE,
-       .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
-       .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
-       .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
-};
-
-MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");
-MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
deleted file mode 100644 (file)
index 827b937..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2014 MediaTek Inc.
- * Author: Jie Qiu <jie.qiu@mediatek.com>
- */
-
-#include "mtk_hdmi_phy.h"
-
-#define HDMI_CON0              0x00
-#define RG_HDMITX_PLL_EN               BIT(31)
-#define RG_HDMITX_PLL_FBKDIV           (0x7f << 24)
-#define PLL_FBKDIV_SHIFT               24
-#define RG_HDMITX_PLL_FBKSEL           (0x3 << 22)
-#define PLL_FBKSEL_SHIFT               22
-#define RG_HDMITX_PLL_PREDIV           (0x3 << 20)
-#define PREDIV_SHIFT                   20
-#define RG_HDMITX_PLL_POSDIV           (0x3 << 18)
-#define POSDIV_SHIFT                   18
-#define RG_HDMITX_PLL_RST_DLY          (0x3 << 16)
-#define RG_HDMITX_PLL_IR               (0xf << 12)
-#define PLL_IR_SHIFT                   12
-#define RG_HDMITX_PLL_IC               (0xf << 8)
-#define PLL_IC_SHIFT                   8
-#define RG_HDMITX_PLL_BP               (0xf << 4)
-#define PLL_BP_SHIFT                   4
-#define RG_HDMITX_PLL_BR               (0x3 << 2)
-#define PLL_BR_SHIFT                   2
-#define RG_HDMITX_PLL_BC               (0x3 << 0)
-#define PLL_BC_SHIFT                   0
-#define HDMI_CON1              0x04
-#define RG_HDMITX_PLL_DIVEN            (0x7 << 29)
-#define PLL_DIVEN_SHIFT                        29
-#define RG_HDMITX_PLL_AUTOK_EN         BIT(28)
-#define RG_HDMITX_PLL_AUTOK_KF         (0x3 << 26)
-#define RG_HDMITX_PLL_AUTOK_KS         (0x3 << 24)
-#define RG_HDMITX_PLL_AUTOK_LOAD       BIT(23)
-#define RG_HDMITX_PLL_BAND             (0x3f << 16)
-#define RG_HDMITX_PLL_REF_SEL          BIT(15)
-#define RG_HDMITX_PLL_BIAS_EN          BIT(14)
-#define RG_HDMITX_PLL_BIAS_LPF_EN      BIT(13)
-#define RG_HDMITX_PLL_TXDIV_EN         BIT(12)
-#define RG_HDMITX_PLL_TXDIV            (0x3 << 10)
-#define PLL_TXDIV_SHIFT                        10
-#define RG_HDMITX_PLL_LVROD_EN         BIT(9)
-#define RG_HDMITX_PLL_MONVC_EN         BIT(8)
-#define RG_HDMITX_PLL_MONCK_EN         BIT(7)
-#define RG_HDMITX_PLL_MONREF_EN                BIT(6)
-#define RG_HDMITX_PLL_TST_EN           BIT(5)
-#define RG_HDMITX_PLL_TST_CK_EN                BIT(4)
-#define RG_HDMITX_PLL_TST_SEL          (0xf << 0)
-#define HDMI_CON2              0x08
-#define RGS_HDMITX_PLL_AUTOK_BAND      (0x7f << 8)
-#define RGS_HDMITX_PLL_AUTOK_FAIL      BIT(1)
-#define RG_HDMITX_EN_TX_CKLDO          BIT(0)
-#define HDMI_CON3              0x0c
-#define RG_HDMITX_SER_EN               (0xf << 28)
-#define RG_HDMITX_PRD_EN               (0xf << 24)
-#define RG_HDMITX_PRD_IMP_EN           (0xf << 20)
-#define RG_HDMITX_DRV_EN               (0xf << 16)
-#define RG_HDMITX_DRV_IMP_EN           (0xf << 12)
-#define DRV_IMP_EN_SHIFT               12
-#define RG_HDMITX_MHLCK_FORCE          BIT(10)
-#define RG_HDMITX_MHLCK_PPIX_EN                BIT(9)
-#define RG_HDMITX_MHLCK_EN             BIT(8)
-#define RG_HDMITX_SER_DIN_SEL          (0xf << 4)
-#define RG_HDMITX_SER_5T1_BIST_EN      BIT(3)
-#define RG_HDMITX_SER_BIST_TOG         BIT(2)
-#define RG_HDMITX_SER_DIN_TOG          BIT(1)
-#define RG_HDMITX_SER_CLKDIG_INV       BIT(0)
-#define HDMI_CON4              0x10
-#define RG_HDMITX_PRD_IBIAS_CLK                (0xf << 24)
-#define RG_HDMITX_PRD_IBIAS_D2         (0xf << 16)
-#define RG_HDMITX_PRD_IBIAS_D1         (0xf << 8)
-#define RG_HDMITX_PRD_IBIAS_D0         (0xf << 0)
-#define PRD_IBIAS_CLK_SHIFT            24
-#define PRD_IBIAS_D2_SHIFT             16
-#define PRD_IBIAS_D1_SHIFT             8
-#define PRD_IBIAS_D0_SHIFT             0
-#define HDMI_CON5              0x14
-#define RG_HDMITX_DRV_IBIAS_CLK                (0x3f << 24)
-#define RG_HDMITX_DRV_IBIAS_D2         (0x3f << 16)
-#define RG_HDMITX_DRV_IBIAS_D1         (0x3f << 8)
-#define RG_HDMITX_DRV_IBIAS_D0         (0x3f << 0)
-#define DRV_IBIAS_CLK_SHIFT            24
-#define DRV_IBIAS_D2_SHIFT             16
-#define DRV_IBIAS_D1_SHIFT             8
-#define DRV_IBIAS_D0_SHIFT             0
-#define HDMI_CON6              0x18
-#define RG_HDMITX_DRV_IMP_CLK          (0x3f << 24)
-#define RG_HDMITX_DRV_IMP_D2           (0x3f << 16)
-#define RG_HDMITX_DRV_IMP_D1           (0x3f << 8)
-#define RG_HDMITX_DRV_IMP_D0           (0x3f << 0)
-#define DRV_IMP_CLK_SHIFT              24
-#define DRV_IMP_D2_SHIFT               16
-#define DRV_IMP_D1_SHIFT               8
-#define DRV_IMP_D0_SHIFT               0
-#define HDMI_CON7              0x1c
-#define RG_HDMITX_MHLCK_DRV_IBIAS      (0x1f << 27)
-#define RG_HDMITX_SER_DIN              (0x3ff << 16)
-#define RG_HDMITX_CHLDC_TST            (0xf << 12)
-#define RG_HDMITX_CHLCK_TST            (0xf << 8)
-#define RG_HDMITX_RESERVE              (0xff << 0)
-#define HDMI_CON8              0x20
-#define RGS_HDMITX_2T1_LEV             (0xf << 16)
-#define RGS_HDMITX_2T1_EDG             (0xf << 12)
-#define RGS_HDMITX_5T1_LEV             (0xf << 8)
-#define RGS_HDMITX_5T1_EDG             (0xf << 4)
-#define RGS_HDMITX_PLUG_TST            BIT(0)
-
-static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_MHLCK_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
-       usleep_range(100, 150);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
-       usleep_range(100, 150);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
-
-       return 0;
-}
-
-static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
-       usleep_range(100, 150);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
-       usleep_range(100, 150);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
-       usleep_range(100, 150);
-}
-
-static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                   unsigned long *parent_rate)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
-       hdmi_phy->pll_rate = rate;
-       if (rate <= 74250000)
-               *parent_rate = rate;
-       else
-               *parent_rate = rate / 2;
-
-       return rate;
-}
-
-static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long parent_rate)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-       unsigned int pre_div;
-       unsigned int div;
-       unsigned int pre_ibias;
-       unsigned int hdmi_ibias;
-       unsigned int imp_en;
-
-       dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__,
-               rate, parent_rate);
-
-       if (rate <= 27000000) {
-               pre_div = 0;
-               div = 3;
-       } else if (rate <= 74250000) {
-               pre_div = 1;
-               div = 2;
-       } else {
-               pre_div = 1;
-               div = 1;
-       }
-
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
-                         (pre_div << PREDIV_SHIFT), RG_HDMITX_PLL_PREDIV);
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
-                         (0x1 << PLL_IC_SHIFT) | (0x1 << PLL_IR_SHIFT),
-                         RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
-                         (div << PLL_TXDIV_SHIFT), RG_HDMITX_PLL_TXDIV);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
-                         (0x1 << PLL_FBKSEL_SHIFT) | (19 << PLL_FBKDIV_SHIFT),
-                         RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
-                         (0x2 << PLL_DIVEN_SHIFT), RG_HDMITX_PLL_DIVEN);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
-                         (0xc << PLL_BP_SHIFT) | (0x2 << PLL_BC_SHIFT) |
-                         (0x1 << PLL_BR_SHIFT),
-                         RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
-                         RG_HDMITX_PLL_BR);
-       if (rate < 165000000) {
-               mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
-                                       RG_HDMITX_PRD_IMP_EN);
-               pre_ibias = 0x3;
-               imp_en = 0x0;
-               hdmi_ibias = hdmi_phy->ibias;
-       } else {
-               mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
-                                     RG_HDMITX_PRD_IMP_EN);
-               pre_ibias = 0x6;
-               imp_en = 0xf;
-               hdmi_ibias = hdmi_phy->ibias_up;
-       }
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
-                         (pre_ibias << PRD_IBIAS_CLK_SHIFT) |
-                         (pre_ibias << PRD_IBIAS_D2_SHIFT) |
-                         (pre_ibias << PRD_IBIAS_D1_SHIFT) |
-                         (pre_ibias << PRD_IBIAS_D0_SHIFT),
-                         RG_HDMITX_PRD_IBIAS_CLK |
-                         RG_HDMITX_PRD_IBIAS_D2 |
-                         RG_HDMITX_PRD_IBIAS_D1 |
-                         RG_HDMITX_PRD_IBIAS_D0);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
-                         (imp_en << DRV_IMP_EN_SHIFT),
-                         RG_HDMITX_DRV_IMP_EN);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
-                         (hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
-                         (hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
-                         (hdmi_phy->drv_imp_d1 << DRV_IMP_D1_SHIFT) |
-                         (hdmi_phy->drv_imp_d0 << DRV_IMP_D0_SHIFT),
-                         RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
-                         RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
-       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
-                         (hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
-                         (hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
-                         (hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
-                         (hdmi_ibias << DRV_IBIAS_D0_SHIFT),
-                         RG_HDMITX_DRV_IBIAS_CLK |
-                         RG_HDMITX_DRV_IBIAS_D2 |
-                         RG_HDMITX_DRV_IBIAS_D1 |
-                         RG_HDMITX_DRV_IBIAS_D0);
-       return 0;
-}
-
-static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
-                                             unsigned long parent_rate)
-{
-       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
-       return hdmi_phy->pll_rate;
-}
-
-static const struct clk_ops mtk_hdmi_phy_pll_ops = {
-       .prepare = mtk_hdmi_pll_prepare,
-       .unprepare = mtk_hdmi_pll_unprepare,
-       .set_rate = mtk_hdmi_pll_set_rate,
-       .round_rate = mtk_hdmi_pll_round_rate,
-       .recalc_rate = mtk_hdmi_pll_recalc_rate,
-};
-
-static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
-{
-       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
-                             RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
-                             RG_HDMITX_DRV_EN);
-       usleep_range(100, 150);
-}
-
-static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
-{
-       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
-                               RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
-                               RG_HDMITX_SER_EN);
-}
-
-struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
-       .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
-       .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
-       .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
-       .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
-};
-
-MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
-MODULE_DESCRIPTION("MediaTek MT8173 HDMI PHY Driver");
-MODULE_LICENSE("GPL v2");
index dee757c..50c5e93 100644 (file)
@@ -35,3 +35,10 @@ config PHY_MTK_XSPHY
          Enable this to support the SuperSpeedPlus XS-PHY transceiver for
          USB3.1 GEN2 controllers on MediaTek chips. The driver supports
          multiple USB2.0, USB3.1 GEN2 ports.
+
+config PHY_MTK_HDMI
+       tristate "MediaTek HDMI-PHY Driver"
+       depends on ARCH_MEDIATEK && OF
+       select GENERIC_PHY
+       help
+         Support HDMI PHY for Mediatek SoCs.
index 08a8e6a..6325e38 100644 (file)
@@ -6,3 +6,8 @@
 obj-$(CONFIG_PHY_MTK_TPHY)             += phy-mtk-tphy.o
 obj-$(CONFIG_PHY_MTK_UFS)              += phy-mtk-ufs.o
 obj-$(CONFIG_PHY_MTK_XSPHY)            += phy-mtk-xsphy.o
+
+phy-mtk-hdmi-drv-y                     := phy-mtk-hdmi.o
+phy-mtk-hdmi-drv-y                     += phy-mtk-hdmi-mt2701.o
+phy-mtk-hdmi-drv-y                     += phy-mtk-hdmi-mt8173.o
+obj-$(CONFIG_PHY_MTK_HDMI)             += phy-mtk-hdmi-drv.o
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c
new file mode 100644 (file)
index 0000000..a6cb1de
--- /dev/null
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Chunhui Dai <chunhui.dai@mediatek.com>
+ */
+
+#include "phy-mtk-hdmi.h"
+
+#define HDMI_CON0      0x00
+#define RG_HDMITX_DRV_IBIAS            0
+#define RG_HDMITX_DRV_IBIAS_MASK       (0x3f << 0)
+#define RG_HDMITX_EN_SER               12
+#define RG_HDMITX_EN_SER_MASK          (0x0f << 12)
+#define RG_HDMITX_EN_SLDO              16
+#define RG_HDMITX_EN_SLDO_MASK         (0x0f << 16)
+#define RG_HDMITX_EN_PRED              20
+#define RG_HDMITX_EN_PRED_MASK         (0x0f << 20)
+#define RG_HDMITX_EN_IMP               24
+#define RG_HDMITX_EN_IMP_MASK          (0x0f << 24)
+#define RG_HDMITX_EN_DRV               28
+#define RG_HDMITX_EN_DRV_MASK          (0x0f << 28)
+
+#define HDMI_CON1      0x04
+#define RG_HDMITX_PRED_IBIAS           18
+#define RG_HDMITX_PRED_IBIAS_MASK      (0x0f << 18)
+#define RG_HDMITX_PRED_IMP             (0x01 << 22)
+#define RG_HDMITX_DRV_IMP              26
+#define RG_HDMITX_DRV_IMP_MASK         (0x3f << 26)
+
+#define HDMI_CON2      0x08
+#define RG_HDMITX_EN_TX_CKLDO          (0x01 << 0)
+#define RG_HDMITX_EN_TX_POSDIV         (0x01 << 1)
+#define RG_HDMITX_TX_POSDIV            3
+#define RG_HDMITX_TX_POSDIV_MASK       (0x03 << 3)
+#define RG_HDMITX_EN_MBIAS             (0x01 << 6)
+#define RG_HDMITX_MBIAS_LPF_EN         (0x01 << 7)
+
+#define HDMI_CON4      0x10
+#define RG_HDMITX_RESERVE_MASK         (0xffffffff << 0)
+
+#define HDMI_CON6      0x18
+#define RG_HTPLL_BR                    0
+#define RG_HTPLL_BR_MASK               (0x03 << 0)
+#define RG_HTPLL_BC                    2
+#define RG_HTPLL_BC_MASK               (0x03 << 2)
+#define RG_HTPLL_BP                    4
+#define RG_HTPLL_BP_MASK               (0x0f << 4)
+#define RG_HTPLL_IR                    8
+#define RG_HTPLL_IR_MASK               (0x0f << 8)
+#define RG_HTPLL_IC                    12
+#define RG_HTPLL_IC_MASK               (0x0f << 12)
+#define RG_HTPLL_POSDIV                        16
+#define RG_HTPLL_POSDIV_MASK           (0x03 << 16)
+#define RG_HTPLL_PREDIV                        18
+#define RG_HTPLL_PREDIV_MASK           (0x03 << 18)
+#define RG_HTPLL_FBKSEL                        20
+#define RG_HTPLL_FBKSEL_MASK           (0x03 << 20)
+#define RG_HTPLL_RLH_EN                        (0x01 << 22)
+#define RG_HTPLL_FBKDIV                        24
+#define RG_HTPLL_FBKDIV_MASK           (0x7f << 24)
+#define RG_HTPLL_EN                    (0x01 << 31)
+
+#define HDMI_CON7      0x1c
+#define RG_HTPLL_AUTOK_EN              (0x01 << 23)
+#define RG_HTPLL_DIVEN                 28
+#define RG_HTPLL_DIVEN_MASK            (0x07 << 28)
+
+static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+       usleep_range(80, 100);
+       return 0;
+}
+
+static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+       usleep_range(80, 100);
+}
+
+static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long *parent_rate)
+{
+       return rate;
+}
+
+static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+       u32 pos_div;
+
+       if (rate <= 64000000)
+               pos_div = 3;
+       else if (rate <= 128000000)
+               pos_div = 2;
+       else
+               pos_div = 1;
+
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
+                         RG_HTPLL_IC_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
+                         RG_HTPLL_IR_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
+                         RG_HDMITX_TX_POSDIV_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
+                         RG_HTPLL_FBKSEL_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
+                         RG_HTPLL_FBKDIV_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
+                         RG_HTPLL_DIVEN_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
+                         RG_HTPLL_BP_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
+                         RG_HTPLL_BC_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
+                         RG_HTPLL_BR_MASK);
+
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
+                         RG_HDMITX_PRED_IBIAS_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
+                         RG_HDMITX_DRV_IMP_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
+                         RG_HDMITX_DRV_IBIAS_MASK);
+       return 0;
+}
+
+static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
+                                             unsigned long parent_rate)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+       unsigned long out_rate, val;
+
+       val = (readl(hdmi_phy->regs + HDMI_CON6)
+              & RG_HTPLL_PREDIV_MASK) >> RG_HTPLL_PREDIV;
+       switch (val) {
+       case 0x00:
+               out_rate = parent_rate;
+               break;
+       case 0x01:
+               out_rate = parent_rate / 2;
+               break;
+       default:
+               out_rate = parent_rate / 4;
+               break;
+       }
+
+       val = (readl(hdmi_phy->regs + HDMI_CON6)
+              & RG_HTPLL_FBKDIV_MASK) >> RG_HTPLL_FBKDIV;
+       out_rate *= (val + 1) * 2;
+       val = (readl(hdmi_phy->regs + HDMI_CON2)
+              & RG_HDMITX_TX_POSDIV_MASK);
+       out_rate >>= (val >> RG_HDMITX_TX_POSDIV);
+
+       if (readl(hdmi_phy->regs + HDMI_CON2) & RG_HDMITX_EN_TX_POSDIV)
+               out_rate /= 5;
+
+       return out_rate;
+}
+
+static const struct clk_ops mtk_hdmi_phy_pll_ops = {
+       .prepare = mtk_hdmi_pll_prepare,
+       .unprepare = mtk_hdmi_pll_unprepare,
+       .set_rate = mtk_hdmi_pll_set_rate,
+       .round_rate = mtk_hdmi_pll_round_rate,
+       .recalc_rate = mtk_hdmi_pll_recalc_rate,
+};
+
+static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
+{
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+       usleep_range(80, 100);
+}
+
+static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
+{
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+       usleep_range(80, 100);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+       usleep_range(80, 100);
+}
+
+struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
+       .flags = CLK_SET_RATE_GATE,
+       .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
+       .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
+       .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
+};
+
+MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8173.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8173.c
new file mode 100644 (file)
index 0000000..6cdfdf5
--- /dev/null
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Jie Qiu <jie.qiu@mediatek.com>
+ */
+
+#include "phy-mtk-hdmi.h"
+
+#define HDMI_CON0              0x00
+#define RG_HDMITX_PLL_EN               BIT(31)
+#define RG_HDMITX_PLL_FBKDIV           (0x7f << 24)
+#define PLL_FBKDIV_SHIFT               24
+#define RG_HDMITX_PLL_FBKSEL           (0x3 << 22)
+#define PLL_FBKSEL_SHIFT               22
+#define RG_HDMITX_PLL_PREDIV           (0x3 << 20)
+#define PREDIV_SHIFT                   20
+#define RG_HDMITX_PLL_POSDIV           (0x3 << 18)
+#define POSDIV_SHIFT                   18
+#define RG_HDMITX_PLL_RST_DLY          (0x3 << 16)
+#define RG_HDMITX_PLL_IR               (0xf << 12)
+#define PLL_IR_SHIFT                   12
+#define RG_HDMITX_PLL_IC               (0xf << 8)
+#define PLL_IC_SHIFT                   8
+#define RG_HDMITX_PLL_BP               (0xf << 4)
+#define PLL_BP_SHIFT                   4
+#define RG_HDMITX_PLL_BR               (0x3 << 2)
+#define PLL_BR_SHIFT                   2
+#define RG_HDMITX_PLL_BC               (0x3 << 0)
+#define PLL_BC_SHIFT                   0
+#define HDMI_CON1              0x04
+#define RG_HDMITX_PLL_DIVEN            (0x7 << 29)
+#define PLL_DIVEN_SHIFT                        29
+#define RG_HDMITX_PLL_AUTOK_EN         BIT(28)
+#define RG_HDMITX_PLL_AUTOK_KF         (0x3 << 26)
+#define RG_HDMITX_PLL_AUTOK_KS         (0x3 << 24)
+#define RG_HDMITX_PLL_AUTOK_LOAD       BIT(23)
+#define RG_HDMITX_PLL_BAND             (0x3f << 16)
+#define RG_HDMITX_PLL_REF_SEL          BIT(15)
+#define RG_HDMITX_PLL_BIAS_EN          BIT(14)
+#define RG_HDMITX_PLL_BIAS_LPF_EN      BIT(13)
+#define RG_HDMITX_PLL_TXDIV_EN         BIT(12)
+#define RG_HDMITX_PLL_TXDIV            (0x3 << 10)
+#define PLL_TXDIV_SHIFT                        10
+#define RG_HDMITX_PLL_LVROD_EN         BIT(9)
+#define RG_HDMITX_PLL_MONVC_EN         BIT(8)
+#define RG_HDMITX_PLL_MONCK_EN         BIT(7)
+#define RG_HDMITX_PLL_MONREF_EN                BIT(6)
+#define RG_HDMITX_PLL_TST_EN           BIT(5)
+#define RG_HDMITX_PLL_TST_CK_EN                BIT(4)
+#define RG_HDMITX_PLL_TST_SEL          (0xf << 0)
+#define HDMI_CON2              0x08
+#define RGS_HDMITX_PLL_AUTOK_BAND      (0x7f << 8)
+#define RGS_HDMITX_PLL_AUTOK_FAIL      BIT(1)
+#define RG_HDMITX_EN_TX_CKLDO          BIT(0)
+#define HDMI_CON3              0x0c
+#define RG_HDMITX_SER_EN               (0xf << 28)
+#define RG_HDMITX_PRD_EN               (0xf << 24)
+#define RG_HDMITX_PRD_IMP_EN           (0xf << 20)
+#define RG_HDMITX_DRV_EN               (0xf << 16)
+#define RG_HDMITX_DRV_IMP_EN           (0xf << 12)
+#define DRV_IMP_EN_SHIFT               12
+#define RG_HDMITX_MHLCK_FORCE          BIT(10)
+#define RG_HDMITX_MHLCK_PPIX_EN                BIT(9)
+#define RG_HDMITX_MHLCK_EN             BIT(8)
+#define RG_HDMITX_SER_DIN_SEL          (0xf << 4)
+#define RG_HDMITX_SER_5T1_BIST_EN      BIT(3)
+#define RG_HDMITX_SER_BIST_TOG         BIT(2)
+#define RG_HDMITX_SER_DIN_TOG          BIT(1)
+#define RG_HDMITX_SER_CLKDIG_INV       BIT(0)
+#define HDMI_CON4              0x10
+#define RG_HDMITX_PRD_IBIAS_CLK                (0xf << 24)
+#define RG_HDMITX_PRD_IBIAS_D2         (0xf << 16)
+#define RG_HDMITX_PRD_IBIAS_D1         (0xf << 8)
+#define RG_HDMITX_PRD_IBIAS_D0         (0xf << 0)
+#define PRD_IBIAS_CLK_SHIFT            24
+#define PRD_IBIAS_D2_SHIFT             16
+#define PRD_IBIAS_D1_SHIFT             8
+#define PRD_IBIAS_D0_SHIFT             0
+#define HDMI_CON5              0x14
+#define RG_HDMITX_DRV_IBIAS_CLK                (0x3f << 24)
+#define RG_HDMITX_DRV_IBIAS_D2         (0x3f << 16)
+#define RG_HDMITX_DRV_IBIAS_D1         (0x3f << 8)
+#define RG_HDMITX_DRV_IBIAS_D0         (0x3f << 0)
+#define DRV_IBIAS_CLK_SHIFT            24
+#define DRV_IBIAS_D2_SHIFT             16
+#define DRV_IBIAS_D1_SHIFT             8
+#define DRV_IBIAS_D0_SHIFT             0
+#define HDMI_CON6              0x18
+#define RG_HDMITX_DRV_IMP_CLK          (0x3f << 24)
+#define RG_HDMITX_DRV_IMP_D2           (0x3f << 16)
+#define RG_HDMITX_DRV_IMP_D1           (0x3f << 8)
+#define RG_HDMITX_DRV_IMP_D0           (0x3f << 0)
+#define DRV_IMP_CLK_SHIFT              24
+#define DRV_IMP_D2_SHIFT               16
+#define DRV_IMP_D1_SHIFT               8
+#define DRV_IMP_D0_SHIFT               0
+#define HDMI_CON7              0x1c
+#define RG_HDMITX_MHLCK_DRV_IBIAS      (0x1f << 27)
+#define RG_HDMITX_SER_DIN              (0x3ff << 16)
+#define RG_HDMITX_CHLDC_TST            (0xf << 12)
+#define RG_HDMITX_CHLCK_TST            (0xf << 8)
+#define RG_HDMITX_RESERVE              (0xff << 0)
+#define HDMI_CON8              0x20
+#define RGS_HDMITX_2T1_LEV             (0xf << 16)
+#define RGS_HDMITX_2T1_EDG             (0xf << 12)
+#define RGS_HDMITX_5T1_LEV             (0xf << 8)
+#define RGS_HDMITX_5T1_EDG             (0xf << 4)
+#define RGS_HDMITX_PLUG_TST            BIT(0)
+
+static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_MHLCK_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
+       usleep_range(100, 150);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
+       usleep_range(100, 150);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
+
+       return 0;
+}
+
+static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
+       usleep_range(100, 150);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
+       usleep_range(100, 150);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
+       usleep_range(100, 150);
+}
+
+static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long *parent_rate)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+       hdmi_phy->pll_rate = rate;
+       if (rate <= 74250000)
+               *parent_rate = rate;
+       else
+               *parent_rate = rate / 2;
+
+       return rate;
+}
+
+static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+       unsigned int pre_div;
+       unsigned int div;
+       unsigned int pre_ibias;
+       unsigned int hdmi_ibias;
+       unsigned int imp_en;
+
+       dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__,
+               rate, parent_rate);
+
+       if (rate <= 27000000) {
+               pre_div = 0;
+               div = 3;
+       } else if (rate <= 74250000) {
+               pre_div = 1;
+               div = 2;
+       } else {
+               pre_div = 1;
+               div = 1;
+       }
+
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
+                         (pre_div << PREDIV_SHIFT), RG_HDMITX_PLL_PREDIV);
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
+                         (0x1 << PLL_IC_SHIFT) | (0x1 << PLL_IR_SHIFT),
+                         RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
+                         (div << PLL_TXDIV_SHIFT), RG_HDMITX_PLL_TXDIV);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
+                         (0x1 << PLL_FBKSEL_SHIFT) | (19 << PLL_FBKDIV_SHIFT),
+                         RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
+                         (0x2 << PLL_DIVEN_SHIFT), RG_HDMITX_PLL_DIVEN);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
+                         (0xc << PLL_BP_SHIFT) | (0x2 << PLL_BC_SHIFT) |
+                         (0x1 << PLL_BR_SHIFT),
+                         RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
+                         RG_HDMITX_PLL_BR);
+       if (rate < 165000000) {
+               mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
+                                       RG_HDMITX_PRD_IMP_EN);
+               pre_ibias = 0x3;
+               imp_en = 0x0;
+               hdmi_ibias = hdmi_phy->ibias;
+       } else {
+               mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
+                                     RG_HDMITX_PRD_IMP_EN);
+               pre_ibias = 0x6;
+               imp_en = 0xf;
+               hdmi_ibias = hdmi_phy->ibias_up;
+       }
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
+                         (pre_ibias << PRD_IBIAS_CLK_SHIFT) |
+                         (pre_ibias << PRD_IBIAS_D2_SHIFT) |
+                         (pre_ibias << PRD_IBIAS_D1_SHIFT) |
+                         (pre_ibias << PRD_IBIAS_D0_SHIFT),
+                         RG_HDMITX_PRD_IBIAS_CLK |
+                         RG_HDMITX_PRD_IBIAS_D2 |
+                         RG_HDMITX_PRD_IBIAS_D1 |
+                         RG_HDMITX_PRD_IBIAS_D0);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
+                         (imp_en << DRV_IMP_EN_SHIFT),
+                         RG_HDMITX_DRV_IMP_EN);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
+                         (hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
+                         (hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
+                         (hdmi_phy->drv_imp_d1 << DRV_IMP_D1_SHIFT) |
+                         (hdmi_phy->drv_imp_d0 << DRV_IMP_D0_SHIFT),
+                         RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
+                         RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
+       mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
+                         (hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
+                         (hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
+                         (hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
+                         (hdmi_ibias << DRV_IBIAS_D0_SHIFT),
+                         RG_HDMITX_DRV_IBIAS_CLK |
+                         RG_HDMITX_DRV_IBIAS_D2 |
+                         RG_HDMITX_DRV_IBIAS_D1 |
+                         RG_HDMITX_DRV_IBIAS_D0);
+       return 0;
+}
+
+static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
+                                             unsigned long parent_rate)
+{
+       struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+       return hdmi_phy->pll_rate;
+}
+
+static const struct clk_ops mtk_hdmi_phy_pll_ops = {
+       .prepare = mtk_hdmi_pll_prepare,
+       .unprepare = mtk_hdmi_pll_unprepare,
+       .set_rate = mtk_hdmi_pll_set_rate,
+       .round_rate = mtk_hdmi_pll_round_rate,
+       .recalc_rate = mtk_hdmi_pll_recalc_rate,
+};
+
+static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
+{
+       mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
+                             RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
+                             RG_HDMITX_DRV_EN);
+       usleep_range(100, 150);
+}
+
+static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
+{
+       mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
+                               RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
+                               RG_HDMITX_SER_EN);
+}
+
+struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
+       .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
+       .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
+       .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
+       .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
+};
+
+MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek MT8173 HDMI PHY Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c
new file mode 100644 (file)
index 0000000..8fc83f0
--- /dev/null
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Jie Qiu <jie.qiu@mediatek.com>
+ */
+
+#include "phy-mtk-hdmi.h"
+
+static int mtk_hdmi_phy_power_on(struct phy *phy);
+static int mtk_hdmi_phy_power_off(struct phy *phy);
+
+static const struct phy_ops mtk_hdmi_phy_dev_ops = {
+       .power_on = mtk_hdmi_phy_power_on,
+       .power_off = mtk_hdmi_phy_power_off,
+       .owner = THIS_MODULE,
+};
+
+void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+                            u32 bits)
+{
+       void __iomem *reg = hdmi_phy->regs + offset;
+       u32 tmp;
+
+       tmp = readl(reg);
+       tmp &= ~bits;
+       writel(tmp, reg);
+}
+
+void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+                          u32 bits)
+{
+       void __iomem *reg = hdmi_phy->regs + offset;
+       u32 tmp;
+
+       tmp = readl(reg);
+       tmp |= bits;
+       writel(tmp, reg);
+}
+
+void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+                      u32 val, u32 mask)
+{
+       void __iomem *reg = hdmi_phy->regs + offset;
+       u32 tmp;
+
+       tmp = readl(reg);
+       tmp = (tmp & ~mask) | (val & mask);
+       writel(tmp, reg);
+}
+
+inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
+{
+       return container_of(hw, struct mtk_hdmi_phy, pll_hw);
+}
+
+static int mtk_hdmi_phy_power_on(struct phy *phy)
+{
+       struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
+       int ret;
+
+       ret = clk_prepare_enable(hdmi_phy->pll);
+       if (ret < 0)
+               return ret;
+
+       hdmi_phy->conf->hdmi_phy_enable_tmds(hdmi_phy);
+       return 0;
+}
+
+static int mtk_hdmi_phy_power_off(struct phy *phy)
+{
+       struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
+
+       hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
+       clk_disable_unprepare(hdmi_phy->pll);
+
+       return 0;
+}
+
+static const struct phy_ops *
+mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
+{
+       if (hdmi_phy && hdmi_phy->conf &&
+           hdmi_phy->conf->hdmi_phy_enable_tmds &&
+           hdmi_phy->conf->hdmi_phy_disable_tmds)
+               return &mtk_hdmi_phy_dev_ops;
+
+       dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
+               return NULL;
+}
+
+static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
+                                     struct clk_init_data *clk_init)
+{
+       clk_init->flags = hdmi_phy->conf->flags;
+       clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops;
+}
+
+static int mtk_hdmi_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct mtk_hdmi_phy *hdmi_phy;
+       struct resource *mem;
+       struct clk *ref_clk;
+       const char *ref_clk_name;
+       struct clk_init_data clk_init = {
+               .num_parents = 1,
+               .parent_names = (const char * const *)&ref_clk_name,
+       };
+
+       struct phy *phy;
+       struct phy_provider *phy_provider;
+       int ret;
+
+       hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
+       if (!hdmi_phy)
+               return -ENOMEM;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       hdmi_phy->regs = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(hdmi_phy->regs)) {
+               ret = PTR_ERR(hdmi_phy->regs);
+               dev_err(dev, "Failed to get memory resource: %d\n", ret);
+               return ret;
+       }
+
+       ref_clk = devm_clk_get(dev, "pll_ref");
+       if (IS_ERR(ref_clk)) {
+               ret = PTR_ERR(ref_clk);
+               dev_err(&pdev->dev, "Failed to get PLL 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;
+       }
+
+       hdmi_phy->dev = dev;
+       hdmi_phy->conf =
+               (struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
+       mtk_hdmi_phy_clk_get_data(hdmi_phy, &clk_init);
+       hdmi_phy->pll_hw.init = &clk_init;
+       hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
+       if (IS_ERR(hdmi_phy->pll)) {
+               ret = PTR_ERR(hdmi_phy->pll);
+               dev_err(dev, "Failed to register PLL: %d\n", ret);
+               return ret;
+       }
+
+       ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
+                                  &hdmi_phy->ibias);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
+               return ret;
+       }
+
+       ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
+                                  &hdmi_phy->ibias_up);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
+               return ret;
+       }
+
+       dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
+       hdmi_phy->drv_imp_clk = 0x30;
+       hdmi_phy->drv_imp_d2 = 0x30;
+       hdmi_phy->drv_imp_d1 = 0x30;
+       hdmi_phy->drv_imp_d0 = 0x30;
+
+       phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy));
+       if (IS_ERR(phy)) {
+               dev_err(dev, "Failed to create HDMI PHY\n");
+               return PTR_ERR(phy);
+       }
+       phy_set_drvdata(phy, hdmi_phy);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(dev, "Failed to register HDMI PHY\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
+                                  hdmi_phy->pll);
+}
+
+static const struct of_device_id mtk_hdmi_phy_match[] = {
+       { .compatible = "mediatek,mt2701-hdmi-phy",
+         .data = &mtk_hdmi_phy_2701_conf,
+       },
+       { .compatible = "mediatek,mt8173-hdmi-phy",
+         .data = &mtk_hdmi_phy_8173_conf,
+       },
+       {},
+};
+
+struct platform_driver mtk_hdmi_phy_driver = {
+       .probe = mtk_hdmi_phy_probe,
+       .driver = {
+               .name = "mediatek-hdmi-phy",
+               .of_match_table = mtk_hdmi_phy_match,
+       },
+};
+module_platform_driver(mtk_hdmi_phy_driver);
+
+MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.h b/drivers/phy/mediatek/phy-mtk-hdmi.h
new file mode 100644 (file)
index 0000000..b13e1d5
--- /dev/null
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Chunhui Dai <chunhui.dai@mediatek.com>
+ */
+
+#ifndef _MTK_HDMI_PHY_H
+#define _MTK_HDMI_PHY_H
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+struct mtk_hdmi_phy;
+
+struct mtk_hdmi_phy_conf {
+       unsigned long flags;
+       const struct clk_ops *hdmi_phy_clk_ops;
+       void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
+       void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
+};
+
+struct mtk_hdmi_phy {
+       void __iomem *regs;
+       struct device *dev;
+       struct mtk_hdmi_phy_conf *conf;
+       struct clk *pll;
+       struct clk_hw pll_hw;
+       unsigned long pll_rate;
+       unsigned char drv_imp_clk;
+       unsigned char drv_imp_d2;
+       unsigned char drv_imp_d1;
+       unsigned char drv_imp_d0;
+       unsigned int ibias;
+       unsigned int ibias_up;
+};
+
+void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+                            u32 bits);
+void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+                          u32 bits);
+void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+                      u32 val, u32 mask);
+struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
+
+extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
+extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf;
+
+#endif /* _MTK_HDMI_PHY_H */