1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
6 #include <linux/of_device.h>
10 static int msm_hdmi_phy_resource_init(struct hdmi_phy
*phy
)
12 struct hdmi_phy_cfg
*cfg
= phy
->cfg
;
13 struct device
*dev
= &phy
->pdev
->dev
;
16 phy
->regs
= devm_kcalloc(dev
, cfg
->num_regs
, sizeof(phy
->regs
[0]),
21 phy
->clks
= devm_kcalloc(dev
, cfg
->num_clks
, sizeof(phy
->clks
[0]),
26 for (i
= 0; i
< cfg
->num_regs
; i
++) {
27 struct regulator
*reg
;
29 reg
= devm_regulator_get(dev
, cfg
->reg_names
[i
]);
32 if (ret
!= -EPROBE_DEFER
) {
34 "failed to get phy regulator: %s (%d)\n",
35 cfg
->reg_names
[i
], ret
);
44 for (i
= 0; i
< cfg
->num_clks
; i
++) {
47 clk
= msm_clk_get(phy
->pdev
, cfg
->clk_names
[i
]);
50 DRM_DEV_ERROR(dev
, "failed to get phy clock: %s (%d)\n",
51 cfg
->clk_names
[i
], ret
);
61 int msm_hdmi_phy_resource_enable(struct hdmi_phy
*phy
)
63 struct hdmi_phy_cfg
*cfg
= phy
->cfg
;
64 struct device
*dev
= &phy
->pdev
->dev
;
67 pm_runtime_get_sync(dev
);
69 for (i
= 0; i
< cfg
->num_regs
; i
++) {
70 ret
= regulator_enable(phy
->regs
[i
]);
72 DRM_DEV_ERROR(dev
, "failed to enable regulator: %s (%d)\n",
73 cfg
->reg_names
[i
], ret
);
76 for (i
= 0; i
< cfg
->num_clks
; i
++) {
77 ret
= clk_prepare_enable(phy
->clks
[i
]);
79 DRM_DEV_ERROR(dev
, "failed to enable clock: %s (%d)\n",
80 cfg
->clk_names
[i
], ret
);
86 void msm_hdmi_phy_resource_disable(struct hdmi_phy
*phy
)
88 struct hdmi_phy_cfg
*cfg
= phy
->cfg
;
89 struct device
*dev
= &phy
->pdev
->dev
;
92 for (i
= cfg
->num_clks
- 1; i
>= 0; i
--)
93 clk_disable_unprepare(phy
->clks
[i
]);
95 for (i
= cfg
->num_regs
- 1; i
>= 0; i
--)
96 regulator_disable(phy
->regs
[i
]);
98 pm_runtime_put_sync(dev
);
101 void msm_hdmi_phy_powerup(struct hdmi_phy
*phy
, unsigned long int pixclock
)
103 if (!phy
|| !phy
->cfg
->powerup
)
106 phy
->cfg
->powerup(phy
, pixclock
);
109 void msm_hdmi_phy_powerdown(struct hdmi_phy
*phy
)
111 if (!phy
|| !phy
->cfg
->powerdown
)
114 phy
->cfg
->powerdown(phy
);
117 static int msm_hdmi_phy_pll_init(struct platform_device
*pdev
,
118 enum hdmi_phy_type type
)
123 case MSM_HDMI_PHY_8960
:
124 ret
= msm_hdmi_pll_8960_init(pdev
);
126 case MSM_HDMI_PHY_8996
:
127 ret
= msm_hdmi_pll_8996_init(pdev
);
130 * we don't have PLL support for these, don't report an error for now
132 case MSM_HDMI_PHY_8x60
:
133 case MSM_HDMI_PHY_8x74
:
142 static int msm_hdmi_phy_probe(struct platform_device
*pdev
)
144 struct device
*dev
= &pdev
->dev
;
145 struct hdmi_phy
*phy
;
148 phy
= devm_kzalloc(dev
, sizeof(*phy
), GFP_KERNEL
);
152 phy
->cfg
= (struct hdmi_phy_cfg
*)of_device_get_match_data(dev
);
156 phy
->mmio
= msm_ioremap(pdev
, "hdmi_phy", "HDMI_PHY");
157 if (IS_ERR(phy
->mmio
)) {
158 DRM_DEV_ERROR(dev
, "%s: failed to map phy base\n", __func__
);
164 ret
= msm_hdmi_phy_resource_init(phy
);
168 pm_runtime_enable(&pdev
->dev
);
170 ret
= msm_hdmi_phy_resource_enable(phy
);
174 ret
= msm_hdmi_phy_pll_init(pdev
, phy
->cfg
->type
);
176 DRM_DEV_ERROR(dev
, "couldn't init PLL\n");
177 msm_hdmi_phy_resource_disable(phy
);
181 msm_hdmi_phy_resource_disable(phy
);
183 platform_set_drvdata(pdev
, phy
);
188 static int msm_hdmi_phy_remove(struct platform_device
*pdev
)
190 pm_runtime_disable(&pdev
->dev
);
195 static const struct of_device_id msm_hdmi_phy_dt_match
[] = {
196 { .compatible
= "qcom,hdmi-phy-8660",
197 .data
= &msm_hdmi_phy_8x60_cfg
},
198 { .compatible
= "qcom,hdmi-phy-8960",
199 .data
= &msm_hdmi_phy_8960_cfg
},
200 { .compatible
= "qcom,hdmi-phy-8974",
201 .data
= &msm_hdmi_phy_8x74_cfg
},
202 { .compatible
= "qcom,hdmi-phy-8084",
203 .data
= &msm_hdmi_phy_8x74_cfg
},
204 { .compatible
= "qcom,hdmi-phy-8996",
205 .data
= &msm_hdmi_phy_8996_cfg
},
209 static struct platform_driver msm_hdmi_phy_platform_driver
= {
210 .probe
= msm_hdmi_phy_probe
,
211 .remove
= msm_hdmi_phy_remove
,
213 .name
= "msm_hdmi_phy",
214 .of_match_table
= msm_hdmi_phy_dt_match
,
218 void __init
msm_hdmi_phy_driver_register(void)
220 platform_driver_register(&msm_hdmi_phy_platform_driver
);
223 void __exit
msm_hdmi_phy_driver_unregister(void)
225 platform_driver_unregister(&msm_hdmi_phy_platform_driver
);