Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: mediatek: phy-mtk-hdmi: Register PHY provided regulator

At least version 2 of the HDMI PHY, found in MediaTek MT8195 and
MT8188 SoCs, does provide hardware support to switch on/off the
HDMI 5V pins (which are also used for DDC), and this translates
to this being a fixed regulator.

Register this PHY-provided regulator so that it can be fed to the
hdmi-connector driver to manage the HDMI +5V PWR rail.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20241120124143.132637-1-angelogioacchino.delregno@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

AngeloGioacchino Del Regno and committed by
Vinod Koul
49393b2d 2318ca59

+79
+44
drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
··· 9 9 #include <linux/module.h> 10 10 #include <linux/phy/phy.h> 11 11 #include <linux/platform_device.h> 12 + #include <linux/regulator/driver.h> 13 + #include <linux/regulator/of_regulator.h> 12 14 #include <linux/types.h> 13 15 #include <linux/units.h> 14 16 #include <linux/nvmem-consumer.h> ··· 480 478 return ret; 481 479 } 482 480 481 + static int mtk_hdmi_phy_pwr5v_enable(struct regulator_dev *rdev) 482 + { 483 + struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev); 484 + 485 + mtk_phy_set_bits(hdmi_phy->regs + HDMI_CTL_1, RG_HDMITX_PWR5V_O); 486 + 487 + return 0; 488 + } 489 + 490 + static int mtk_hdmi_phy_pwr5v_disable(struct regulator_dev *rdev) 491 + { 492 + struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev); 493 + 494 + mtk_phy_clear_bits(hdmi_phy->regs + HDMI_CTL_1, RG_HDMITX_PWR5V_O); 495 + 496 + return 0; 497 + } 498 + 499 + static int mtk_hdmi_phy_pwr5v_is_enabled(struct regulator_dev *rdev) 500 + { 501 + struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev); 502 + 503 + return !!(readl(hdmi_phy->regs + HDMI_CTL_1) & RG_HDMITX_PWR5V_O); 504 + } 505 + 506 + static const struct regulator_ops mtk_hdmi_pwr5v_regulator_ops = { 507 + .enable = mtk_hdmi_phy_pwr5v_enable, 508 + .disable = mtk_hdmi_phy_pwr5v_disable, 509 + .is_enabled = mtk_hdmi_phy_pwr5v_is_enabled 510 + }; 511 + 512 + static const struct regulator_desc mtk_hdmi_phy_pwr5v_desc = { 513 + .name = "hdmi-pwr5v", 514 + .id = -1, 515 + .n_voltages = 1, 516 + .fixed_uV = 5000000, 517 + .ops = &mtk_hdmi_pwr5v_regulator_ops, 518 + .type = REGULATOR_VOLTAGE, 519 + .owner = THIS_MODULE, 520 + }; 521 + 483 522 struct mtk_hdmi_phy_conf mtk_hdmi_phy_8195_conf = { 484 523 .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, 524 + .hdmi_phy_regulator_desc = &mtk_hdmi_phy_pwr5v_desc, 485 525 .hdmi_phy_clk_ops = &mtk_hdmi_pll_ops, 486 526 .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds, 487 527 .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
+3
drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h
··· 103 103 #define HDMI_ANA_CTL 0x7c 104 104 #define REG_ANA_HDMI20_FIFO_EN BIT(16) 105 105 106 + #define HDMI_CTL_1 0xc4 107 + #define RG_HDMITX_PWR5V_O BIT(9) 108 + 106 109 #define HDMI_CTL_3 0xcc 107 110 #define REG_HDMITXPLL_DIV GENMASK(4, 0) 108 111 #define REG_HDMITX_REF_XTAL_SEL BIT(7)
+28
drivers/phy/mediatek/phy-mtk-hdmi.c
··· 75 75 clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops; 76 76 } 77 77 78 + static int mtk_hdmi_phy_register_regulators(struct mtk_hdmi_phy *hdmi_phy) 79 + { 80 + const struct regulator_desc *vreg_desc = hdmi_phy->conf->hdmi_phy_regulator_desc; 81 + const struct regulator_init_data vreg_init_data = { 82 + .constraints = { 83 + .valid_ops_mask = REGULATOR_CHANGE_STATUS, 84 + } 85 + }; 86 + struct regulator_config vreg_config = { 87 + .dev = hdmi_phy->dev, 88 + .driver_data = hdmi_phy, 89 + .init_data = &vreg_init_data, 90 + .of_node = hdmi_phy->dev->of_node 91 + }; 92 + 93 + hdmi_phy->rdev = devm_regulator_register(hdmi_phy->dev, vreg_desc, &vreg_config); 94 + if (IS_ERR(hdmi_phy->rdev)) 95 + return PTR_ERR(hdmi_phy->rdev); 96 + 97 + return 0; 98 + } 99 + 78 100 static int mtk_hdmi_phy_probe(struct platform_device *pdev) 79 101 { 80 102 struct device *dev = &pdev->dev; ··· 171 149 172 150 if (hdmi_phy->conf->pll_default_off) 173 151 hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy); 152 + 153 + if (hdmi_phy->conf->hdmi_phy_regulator_desc) { 154 + ret = mtk_hdmi_phy_register_regulators(hdmi_phy); 155 + if (ret) 156 + return ret; 157 + } 174 158 175 159 return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, 176 160 hdmi_phy->pll);
+4
drivers/phy/mediatek/phy-mtk-hdmi.h
··· 13 13 #include <linux/module.h> 14 14 #include <linux/phy/phy.h> 15 15 #include <linux/platform_device.h> 16 + #include <linux/regulator/driver.h> 17 + #include <linux/regulator/machine.h> 16 18 #include <linux/types.h> 17 19 18 20 struct mtk_hdmi_phy; ··· 22 20 struct mtk_hdmi_phy_conf { 23 21 unsigned long flags; 24 22 bool pll_default_off; 23 + const struct regulator_desc *hdmi_phy_regulator_desc; 25 24 const struct clk_ops *hdmi_phy_clk_ops; 26 25 void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy); 27 26 void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy); ··· 35 32 struct mtk_hdmi_phy_conf *conf; 36 33 struct clk *pll; 37 34 struct clk_hw pll_hw; 35 + struct regulator_dev *rdev; 38 36 unsigned long pll_rate; 39 37 unsigned char drv_imp_clk; 40 38 unsigned char drv_imp_d2;