diff options
Diffstat (limited to 'drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c')
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c index 69c3ec0938f7..5547f8df8e71 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -94,8 +94,8 @@ #define LCPLL_ALONE_MODE BIT(1) /* CMN_REG(0097) */ #define DIG_CLK_SEL BIT(1) -#define ROPLL_REF BIT(1) -#define LCPLL_REF 0 +#define LCPLL_REF BIT(1) +#define ROPLL_REF 0 /* CMN_REG(0099) */ #define CMN_ROPLL_ALONE_MODE BIT(2) #define ROPLL_ALONE_MODE BIT(2) @@ -192,6 +192,7 @@ #define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) #define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) +#define HDMI14_MAX_RATE 340000000 #define HDMI20_MAX_RATE 600000000 struct lcpll_config { @@ -266,11 +267,22 @@ enum rk_hdptx_reset { RST_MAX }; +#define MAX_HDPTX_PHY_NUM 2 + +struct rk_hdptx_phy_cfg { + unsigned int num_phys; + unsigned int phy_ids[MAX_HDPTX_PHY_NUM]; +}; + struct rk_hdptx_phy { struct device *dev; struct regmap *regmap; struct regmap *grf; + /* PHY const config */ + const struct rk_hdptx_phy_cfg *cfgs; + int phy_id; + struct phy *phy; struct phy_config *phy_cfg; struct clk_bulk_data *clks; @@ -317,6 +329,8 @@ static const struct ropll_config ropll_tmds_cfg[] = { 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, + { 502500, 84, 84, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 11, 1, 4, 5, + 4, 11, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5, 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, @@ -767,9 +781,7 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, { const struct ropll_config *cfg = NULL; struct ropll_config rc = {0}; - int i; - - hdptx->rate = rate * 100; + int ret, i; for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) if (rate == ropll_tmds_cfg[i].bit_rate) { @@ -828,7 +840,11 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, PLL_PCG_CLK_EN); - return rk_hdptx_post_enable_pll(hdptx); + ret = rk_hdptx_post_enable_pll(hdptx); + if (!ret) + hdptx->rate = rate * 100; + + return ret; } static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, @@ -838,7 +854,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06); - if (rate >= 3400000) { + if (rate > HDMI14_MAX_RATE / 100) { /* For 1/40 bitrate clk */ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq); } else { @@ -1019,15 +1035,14 @@ static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx) struct device *dev = hdptx->dev; const char *name, *pname; struct clk *refclk; - int ret, id; + int ret; refclk = devm_clk_get(dev, "ref"); if (IS_ERR(refclk)) return dev_err_probe(dev, PTR_ERR(refclk), "Failed to get ref clock\n"); - id = of_alias_get_id(dev->of_node, "hdptxphy"); - name = id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; + name = hdptx->phy_id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; pname = __clk_get_name(refclk); hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, @@ -1070,8 +1085,9 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; struct device *dev = &pdev->dev; struct rk_hdptx_phy *hdptx; + struct resource *res; void __iomem *regs; - int ret; + int ret, id; hdptx = devm_kzalloc(dev, sizeof(*hdptx), GFP_KERNEL); if (!hdptx) @@ -1079,11 +1095,27 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) hdptx->dev = dev; - regs = devm_platform_ioremap_resource(pdev, 0); + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(regs)) return dev_err_probe(dev, PTR_ERR(regs), "Failed to ioremap resource\n"); + hdptx->cfgs = device_get_match_data(dev); + if (!hdptx->cfgs) + return dev_err_probe(dev, -EINVAL, "missing match data\n"); + + /* find the phy-id from the io address */ + hdptx->phy_id = -ENODEV; + for (id = 0; id < hdptx->cfgs->num_phys; id++) { + if (res->start == hdptx->cfgs->phy_ids[id]) { + hdptx->phy_id = id; + break; + } + } + + if (hdptx->phy_id < 0) + return dev_err_probe(dev, -ENODEV, "no matching device found\n"); + ret = devm_clk_bulk_get_all(dev, &hdptx->clks); if (ret < 0) return dev_err_probe(dev, ret, "Failed to get clocks\n"); @@ -1147,8 +1179,19 @@ static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { rk_hdptx_phy_runtime_resume, NULL) }; +static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = { + .num_phys = 2, + .phy_ids = { + 0xfed60000, + 0xfed70000, + }, +}; + static const struct of_device_id rk_hdptx_phy_of_match[] = { - { .compatible = "rockchip,rk3588-hdptx-phy", }, + { + .compatible = "rockchip,rk3588-hdptx-phy", + .data = &rk3588_hdptx_phy_cfgs + }, {} }; MODULE_DEVICE_TABLE(of, rk_hdptx_phy_of_match); |