goto err_disable_clk_tmds;
}
+ ret = sun8i_hdmi_phy_init(hdmi->phy);
+ if (ret)
+ goto err_disable_clk_tmds;
+
drm_encoder_helper_add(encoder, &sun8i_dw_hdmi_encoder_helper_funcs);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
- sun8i_hdmi_phy_init(hdmi->phy);
-
plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe;
sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data);
struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev);
dw_hdmi_unbind(hdmi->hdmi);
+ sun8i_hdmi_phy_deinit(hdmi->phy);
clk_disable_unprepare(hdmi->clk_tmds);
reset_control_assert(hdmi->rst_ctrl);
gpiod_set_value(hdmi->ddc_en, 0);
phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2;
}
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
{
+ int ret;
+
+ ret = reset_control_deassert(phy->rst_phy);
+ if (ret) {
+ dev_err(phy->dev, "Cannot deassert phy reset control: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(phy->clk_bus);
+ if (ret) {
+ dev_err(phy->dev, "Cannot enable bus clock: %d\n", ret);
+ goto err_assert_rst_phy;
+ }
+
+ ret = clk_prepare_enable(phy->clk_mod);
+ if (ret) {
+ dev_err(phy->dev, "Cannot enable mod clock: %d\n", ret);
+ goto err_disable_clk_bus;
+ }
+
+ if (phy->variant->has_phy_clk) {
+ ret = sun8i_phy_clk_create(phy, phy->dev,
+ phy->variant->has_second_pll);
+ if (ret) {
+ dev_err(phy->dev, "Couldn't create the PHY clock\n");
+ goto err_disable_clk_mod;
+ }
+
+ clk_prepare_enable(phy->clk_phy);
+ }
+
phy->variant->phy_init(phy);
+
+ return 0;
+
+err_disable_clk_mod:
+ clk_disable_unprepare(phy->clk_mod);
+err_disable_clk_bus:
+ clk_disable_unprepare(phy->clk_bus);
+err_assert_rst_phy:
+ reset_control_assert(phy->rst_phy);
+
+ return ret;
+}
+
+void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy)
+{
+ clk_disable_unprepare(phy->clk_mod);
+ clk_disable_unprepare(phy->clk_bus);
+ clk_disable_unprepare(phy->clk_phy);
+
+ reset_control_assert(phy->rst_phy);
}
void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
return -ENOMEM;
phy->variant = (struct sun8i_hdmi_phy_variant *)match->data;
+ phy->dev = dev;
ret = of_address_to_resource(node, 0, &res);
if (ret) {
goto err_put_clk_pll1;
}
- ret = reset_control_deassert(phy->rst_phy);
- if (ret) {
- dev_err(dev, "Cannot deassert phy reset control: %d\n", ret);
- goto err_put_rst_phy;
- }
-
- ret = clk_prepare_enable(phy->clk_bus);
- if (ret) {
- dev_err(dev, "Cannot enable bus clock: %d\n", ret);
- goto err_deassert_rst_phy;
- }
-
- ret = clk_prepare_enable(phy->clk_mod);
- if (ret) {
- dev_err(dev, "Cannot enable mod clock: %d\n", ret);
- goto err_disable_clk_bus;
- }
-
- if (phy->variant->has_phy_clk) {
- ret = sun8i_phy_clk_create(phy, dev,
- phy->variant->has_second_pll);
- if (ret) {
- dev_err(dev, "Couldn't create the PHY clock\n");
- goto err_disable_clk_mod;
- }
-
- clk_prepare_enable(phy->clk_phy);
- }
-
platform_set_drvdata(pdev, phy);
return 0;
-err_disable_clk_mod:
- clk_disable_unprepare(phy->clk_mod);
-err_disable_clk_bus:
- clk_disable_unprepare(phy->clk_bus);
-err_deassert_rst_phy:
- reset_control_assert(phy->rst_phy);
-err_put_rst_phy:
- reset_control_put(phy->rst_phy);
err_put_clk_pll1:
clk_put(phy->clk_pll1);
err_put_clk_pll0:
{
struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);
- clk_disable_unprepare(phy->clk_mod);
- clk_disable_unprepare(phy->clk_bus);
- clk_disable_unprepare(phy->clk_phy);
-
- reset_control_assert(phy->rst_phy);
-
reset_control_put(phy->rst_phy);
clk_put(phy->clk_pll0);