forked from mirrors/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>
This commit is contained in:
		
							parent
							
								
									2318ca5994
								
							
						
					
					
						commit
						49393b2da1
					
				
					 4 changed files with 79 additions and 0 deletions
				
			
		| 
						 | 
					@ -9,6 +9,8 @@
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/phy/phy.h>
 | 
					#include <linux/phy/phy.h>
 | 
				
			||||||
#include <linux/platform_device.h>
 | 
					#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					#include <linux/regulator/driver.h>
 | 
				
			||||||
 | 
					#include <linux/regulator/of_regulator.h>
 | 
				
			||||||
#include <linux/types.h>
 | 
					#include <linux/types.h>
 | 
				
			||||||
#include <linux/units.h>
 | 
					#include <linux/units.h>
 | 
				
			||||||
#include <linux/nvmem-consumer.h>
 | 
					#include <linux/nvmem-consumer.h>
 | 
				
			||||||
| 
						 | 
					@ -478,8 +480,50 @@ static int mtk_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opt
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mtk_hdmi_phy_pwr5v_enable(struct regulator_dev *rdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mtk_phy_set_bits(hdmi_phy->regs + HDMI_CTL_1, RG_HDMITX_PWR5V_O);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mtk_hdmi_phy_pwr5v_disable(struct regulator_dev *rdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mtk_phy_clear_bits(hdmi_phy->regs + HDMI_CTL_1, RG_HDMITX_PWR5V_O);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mtk_hdmi_phy_pwr5v_is_enabled(struct regulator_dev *rdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return !!(readl(hdmi_phy->regs + HDMI_CTL_1) & RG_HDMITX_PWR5V_O);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct regulator_ops mtk_hdmi_pwr5v_regulator_ops = {
 | 
				
			||||||
 | 
						.enable = mtk_hdmi_phy_pwr5v_enable,
 | 
				
			||||||
 | 
						.disable = mtk_hdmi_phy_pwr5v_disable,
 | 
				
			||||||
 | 
						.is_enabled = mtk_hdmi_phy_pwr5v_is_enabled
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct regulator_desc mtk_hdmi_phy_pwr5v_desc = {
 | 
				
			||||||
 | 
						.name = "hdmi-pwr5v",
 | 
				
			||||||
 | 
						.id = -1,
 | 
				
			||||||
 | 
						.n_voltages = 1,
 | 
				
			||||||
 | 
						.fixed_uV = 5000000,
 | 
				
			||||||
 | 
						.ops = &mtk_hdmi_pwr5v_regulator_ops,
 | 
				
			||||||
 | 
						.type = REGULATOR_VOLTAGE,
 | 
				
			||||||
 | 
						.owner = THIS_MODULE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mtk_hdmi_phy_conf mtk_hdmi_phy_8195_conf = {
 | 
					struct mtk_hdmi_phy_conf mtk_hdmi_phy_8195_conf = {
 | 
				
			||||||
	.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
 | 
						.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
 | 
				
			||||||
 | 
						.hdmi_phy_regulator_desc = &mtk_hdmi_phy_pwr5v_desc,
 | 
				
			||||||
	.hdmi_phy_clk_ops = &mtk_hdmi_pll_ops,
 | 
						.hdmi_phy_clk_ops = &mtk_hdmi_pll_ops,
 | 
				
			||||||
	.hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
 | 
						.hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
 | 
				
			||||||
	.hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
 | 
						.hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,6 +103,9 @@
 | 
				
			||||||
#define HDMI_ANA_CTL 0x7c
 | 
					#define HDMI_ANA_CTL 0x7c
 | 
				
			||||||
#define REG_ANA_HDMI20_FIFO_EN BIT(16)
 | 
					#define REG_ANA_HDMI20_FIFO_EN BIT(16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HDMI_CTL_1 0xc4
 | 
				
			||||||
 | 
					#define RG_HDMITX_PWR5V_O BIT(9)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HDMI_CTL_3 0xcc
 | 
					#define HDMI_CTL_3 0xcc
 | 
				
			||||||
#define REG_HDMITXPLL_DIV GENMASK(4, 0)
 | 
					#define REG_HDMITXPLL_DIV GENMASK(4, 0)
 | 
				
			||||||
#define REG_HDMITX_REF_XTAL_SEL BIT(7)
 | 
					#define REG_HDMITX_REF_XTAL_SEL BIT(7)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,6 +75,28 @@ static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
 | 
				
			||||||
	clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops;
 | 
						clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mtk_hdmi_phy_register_regulators(struct mtk_hdmi_phy *hdmi_phy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct regulator_desc *vreg_desc = hdmi_phy->conf->hdmi_phy_regulator_desc;
 | 
				
			||||||
 | 
						const struct regulator_init_data vreg_init_data = {
 | 
				
			||||||
 | 
							.constraints = {
 | 
				
			||||||
 | 
								.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct regulator_config vreg_config = {
 | 
				
			||||||
 | 
							.dev = hdmi_phy->dev,
 | 
				
			||||||
 | 
							.driver_data = hdmi_phy,
 | 
				
			||||||
 | 
							.init_data = &vreg_init_data,
 | 
				
			||||||
 | 
							.of_node = hdmi_phy->dev->of_node
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hdmi_phy->rdev = devm_regulator_register(hdmi_phy->dev, vreg_desc, &vreg_config);
 | 
				
			||||||
 | 
						if (IS_ERR(hdmi_phy->rdev))
 | 
				
			||||||
 | 
							return PTR_ERR(hdmi_phy->rdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mtk_hdmi_phy_probe(struct platform_device *pdev)
 | 
					static int mtk_hdmi_phy_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device *dev = &pdev->dev;
 | 
						struct device *dev = &pdev->dev;
 | 
				
			||||||
| 
						 | 
					@ -150,6 +172,12 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
 | 
				
			||||||
	if (hdmi_phy->conf->pll_default_off)
 | 
						if (hdmi_phy->conf->pll_default_off)
 | 
				
			||||||
		hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
 | 
							hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hdmi_phy->conf->hdmi_phy_regulator_desc) {
 | 
				
			||||||
 | 
							ret = mtk_hdmi_phy_register_regulators(hdmi_phy);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
 | 
						return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
 | 
				
			||||||
				   hdmi_phy->pll);
 | 
									   hdmi_phy->pll);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,8 @@
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/phy/phy.h>
 | 
					#include <linux/phy/phy.h>
 | 
				
			||||||
#include <linux/platform_device.h>
 | 
					#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					#include <linux/regulator/driver.h>
 | 
				
			||||||
 | 
					#include <linux/regulator/machine.h>
 | 
				
			||||||
#include <linux/types.h>
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mtk_hdmi_phy;
 | 
					struct mtk_hdmi_phy;
 | 
				
			||||||
| 
						 | 
					@ -20,6 +22,7 @@ struct mtk_hdmi_phy;
 | 
				
			||||||
struct mtk_hdmi_phy_conf {
 | 
					struct mtk_hdmi_phy_conf {
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	bool pll_default_off;
 | 
						bool pll_default_off;
 | 
				
			||||||
 | 
						const struct regulator_desc *hdmi_phy_regulator_desc;
 | 
				
			||||||
	const struct clk_ops *hdmi_phy_clk_ops;
 | 
						const struct clk_ops *hdmi_phy_clk_ops;
 | 
				
			||||||
	void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
 | 
						void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
 | 
				
			||||||
	void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
 | 
						void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
 | 
				
			||||||
| 
						 | 
					@ -32,6 +35,7 @@ struct mtk_hdmi_phy {
 | 
				
			||||||
	struct mtk_hdmi_phy_conf *conf;
 | 
						struct mtk_hdmi_phy_conf *conf;
 | 
				
			||||||
	struct clk *pll;
 | 
						struct clk *pll;
 | 
				
			||||||
	struct clk_hw pll_hw;
 | 
						struct clk_hw pll_hw;
 | 
				
			||||||
 | 
						struct regulator_dev *rdev;
 | 
				
			||||||
	unsigned long pll_rate;
 | 
						unsigned long pll_rate;
 | 
				
			||||||
	unsigned char drv_imp_clk;
 | 
						unsigned char drv_imp_clk;
 | 
				
			||||||
	unsigned char drv_imp_d2;
 | 
						unsigned char drv_imp_d2;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue