1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
7 #include <linux/platform_device.h>
11 static int msm_hdmi_phy_resource_init(struct hdmi_phy
*phy
)
13 struct hdmi_phy_cfg
*cfg
= phy
->cfg
;
14 struct device
*dev
= &phy
->pdev
->dev
;
17 phy
->regs
= devm_kcalloc(dev
, cfg
->num_regs
, sizeof(phy
->regs
[0]),
22 phy
->clks
= devm_kcalloc(dev
, cfg
->num_clks
, sizeof(phy
->clks
[0]),
27 for (i
= 0; i
< cfg
->num_regs
; i
++)
28 phy
->regs
[i
].supply
= cfg
->reg_names
[i
];
30 ret
= devm_regulator_bulk_get(dev
, cfg
->num_regs
, phy
->regs
);
32 if (ret
!= -EPROBE_DEFER
)
33 DRM_DEV_ERROR(dev
, "failed to get phy regulators: %d\n", ret
);
38 for (i
= 0; i
< cfg
->num_clks
; i
++) {
41 clk
= msm_clk_get(phy
->pdev
, cfg
->clk_names
[i
]);
44 DRM_DEV_ERROR(dev
, "failed to get phy clock: %s (%d)\n",
45 cfg
->clk_names
[i
], ret
);
55 int msm_hdmi_phy_resource_enable(struct hdmi_phy
*phy
)
57 struct hdmi_phy_cfg
*cfg
= phy
->cfg
;
58 struct device
*dev
= &phy
->pdev
->dev
;
61 pm_runtime_get_sync(dev
);
63 ret
= regulator_bulk_enable(cfg
->num_regs
, phy
->regs
);
65 DRM_DEV_ERROR(dev
, "failed to enable regulators: (%d)\n", ret
);
69 for (i
= 0; i
< cfg
->num_clks
; i
++) {
70 ret
= clk_prepare_enable(phy
->clks
[i
]);
72 DRM_DEV_ERROR(dev
, "failed to enable clock: %s (%d)\n",
73 cfg
->clk_names
[i
], ret
);
79 void msm_hdmi_phy_resource_disable(struct hdmi_phy
*phy
)
81 struct hdmi_phy_cfg
*cfg
= phy
->cfg
;
82 struct device
*dev
= &phy
->pdev
->dev
;
85 for (i
= cfg
->num_clks
- 1; i
>= 0; i
--)
86 clk_disable_unprepare(phy
->clks
[i
]);
88 regulator_bulk_disable(cfg
->num_regs
, phy
->regs
);
90 pm_runtime_put_sync(dev
);
93 void msm_hdmi_phy_powerup(struct hdmi_phy
*phy
, unsigned long int pixclock
)
95 if (!phy
|| !phy
->cfg
->powerup
)
98 phy
->cfg
->powerup(phy
, pixclock
);
101 void msm_hdmi_phy_powerdown(struct hdmi_phy
*phy
)
103 if (!phy
|| !phy
->cfg
->powerdown
)
106 phy
->cfg
->powerdown(phy
);
109 static int msm_hdmi_phy_pll_init(struct platform_device
*pdev
,
110 enum hdmi_phy_type type
)
115 case MSM_HDMI_PHY_8960
:
116 ret
= msm_hdmi_pll_8960_init(pdev
);
118 case MSM_HDMI_PHY_8996
:
119 ret
= msm_hdmi_pll_8996_init(pdev
);
121 case MSM_HDMI_PHY_8998
:
122 ret
= msm_hdmi_pll_8998_init(pdev
);
125 * we don't have PLL support for these, don't report an error for now
127 case MSM_HDMI_PHY_8x60
:
128 case MSM_HDMI_PHY_8x74
:
137 static int msm_hdmi_phy_probe(struct platform_device
*pdev
)
139 struct device
*dev
= &pdev
->dev
;
140 struct hdmi_phy
*phy
;
143 phy
= devm_kzalloc(dev
, sizeof(*phy
), GFP_KERNEL
);
147 phy
->cfg
= (struct hdmi_phy_cfg
*)of_device_get_match_data(dev
);
151 phy
->mmio
= msm_ioremap(pdev
, "hdmi_phy");
152 if (IS_ERR(phy
->mmio
)) {
153 DRM_DEV_ERROR(dev
, "%s: failed to map phy base\n", __func__
);
159 ret
= msm_hdmi_phy_resource_init(phy
);
163 pm_runtime_enable(&pdev
->dev
);
165 ret
= msm_hdmi_phy_resource_enable(phy
);
169 ret
= msm_hdmi_phy_pll_init(pdev
, phy
->cfg
->type
);
171 DRM_DEV_ERROR(dev
, "couldn't init PLL\n");
172 msm_hdmi_phy_resource_disable(phy
);
176 msm_hdmi_phy_resource_disable(phy
);
178 platform_set_drvdata(pdev
, phy
);
183 static void msm_hdmi_phy_remove(struct platform_device
*pdev
)
185 pm_runtime_disable(&pdev
->dev
);
188 static const struct of_device_id msm_hdmi_phy_dt_match
[] = {
189 { .compatible
= "qcom,hdmi-phy-8660",
190 .data
= &msm_hdmi_phy_8x60_cfg
},
191 { .compatible
= "qcom,hdmi-phy-8960",
192 .data
= &msm_hdmi_phy_8960_cfg
},
193 { .compatible
= "qcom,hdmi-phy-8974",
194 .data
= &msm_hdmi_phy_8x74_cfg
},
195 { .compatible
= "qcom,hdmi-phy-8084",
196 .data
= &msm_hdmi_phy_8x74_cfg
},
197 { .compatible
= "qcom,hdmi-phy-8996",
198 .data
= &msm_hdmi_phy_8996_cfg
},
199 { .compatible
= "qcom,hdmi-phy-8998",
200 .data
= &msm_hdmi_phy_8998_cfg
},
204 static struct platform_driver msm_hdmi_phy_platform_driver
= {
205 .probe
= msm_hdmi_phy_probe
,
206 .remove
= msm_hdmi_phy_remove
,
208 .name
= "msm_hdmi_phy",
209 .of_match_table
= msm_hdmi_phy_dt_match
,
213 void __init
msm_hdmi_phy_driver_register(void)
215 platform_driver_register(&msm_hdmi_phy_platform_driver
);
218 void __exit
msm_hdmi_phy_driver_unregister(void)
220 platform_driver_unregister(&msm_hdmi_phy_platform_driver
);