mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-30 06:06:43 +00:00
Merge pull request #5626 from jernejsk/aw-hdmi-fix
Allwinner: linux: Fix HDMI driver
This commit is contained in:
commit
2d87cff8b0
@ -140,7 +140,7 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
.is_custom_phy = true,
|
.is_custom_phy = true,
|
||||||
.phy_init = &sun8i_hdmi_phy_init_h3,
|
.phy_init = &sun8i_hdmi_phy_init_h3,
|
||||||
@@ -725,10 +766,36 @@ static int sun8i_hdmi_phy_probe(struct p
|
@@ -725,10 +766,36 @@ static int sun8i_hdmi_phy_probe(struct p
|
||||||
clk_prepare_enable(phy->clk_phy);
|
goto err_put_clk_pll1;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ if (phy->variant->bit_bang_cec) {
|
+ if (phy->variant->bit_bang_cec) {
|
||||||
@ -173,9 +173,9 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
+ cec_delete_adapter(phy->cec_adapter);
|
+ cec_delete_adapter(phy->cec_adapter);
|
||||||
+err_disable_clk_phy:
|
+err_disable_clk_phy:
|
||||||
+ clk_disable_unprepare(phy->clk_phy);
|
+ clk_disable_unprepare(phy->clk_phy);
|
||||||
err_disable_clk_mod:
|
err_put_clk_pll1:
|
||||||
clk_disable_unprepare(phy->clk_mod);
|
clk_put(phy->clk_pll1);
|
||||||
err_disable_clk_bus:
|
err_put_clk_pll0:
|
||||||
@@ -753,6 +820,9 @@ static int sun8i_hdmi_phy_remove(struct
|
@@ -753,6 +820,9 @@ static int sun8i_hdmi_phy_remove(struct
|
||||||
{
|
{
|
||||||
struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);
|
struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);
|
||||||
@ -183,6 +183,6 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
+ cec_notifier_cec_adap_unregister(phy->cec_notifier, phy->cec_adapter);
|
+ cec_notifier_cec_adap_unregister(phy->cec_notifier, phy->cec_adapter);
|
||||||
+ cec_unregister_adapter(phy->cec_adapter);
|
+ cec_unregister_adapter(phy->cec_adapter);
|
||||||
+
|
+
|
||||||
clk_disable_unprepare(phy->clk_mod);
|
reset_control_put(phy->rst_phy);
|
||||||
clk_disable_unprepare(phy->clk_bus);
|
|
||||||
clk_disable_unprepare(phy->clk_phy);
|
clk_put(phy->clk_pll0);
|
||||||
|
@ -0,0 +1,210 @@
|
|||||||
|
From 887d1018e2c5ab5e81edbd1318bbf4bbd2c739b0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Sun, 12 Sep 2021 20:15:26 +0200
|
||||||
|
Subject: [PATCH] drm/sun4i: dw-hdmi: Fix HDMI PHY clock setup
|
||||||
|
|
||||||
|
Recent rework which made HDMI PHY driver a platform device inadvertely
|
||||||
|
reversed clock setup order. HW is very touch about it. Proper way is to
|
||||||
|
handle controllers resets and clocks first and HDMI PHYs second.
|
||||||
|
|
||||||
|
Move HDMI PHY reset & clocks handling to sun8i_hdmi_phy_init() which
|
||||||
|
will assure that code is executed after controllers reset & clocks are
|
||||||
|
handled. Additionally, add sun8i_hdmi_phy_deinit() which will deinit it
|
||||||
|
at controllers driver unload.
|
||||||
|
|
||||||
|
Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 7 +-
|
||||||
|
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 4 +-
|
||||||
|
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 97 ++++++++++++++------------
|
||||||
|
3 files changed, 61 insertions(+), 47 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
|
||||||
|
index f75fb157f2ff..5fa5407ac583 100644
|
||||||
|
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
|
||||||
|
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
|
||||||
|
@@ -216,11 +216,13 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
goto err_disable_clk_tmds;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ret = sun8i_hdmi_phy_init(hdmi->phy);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
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);
|
||||||
|
@@ -262,6 +264,7 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master,
|
||||||
|
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);
|
||||||
|
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
|
||||||
|
index 74f6ed0e2570..bffe1b9cd3dc 100644
|
||||||
|
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
|
||||||
|
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
|
||||||
|
@@ -169,6 +169,7 @@ struct sun8i_hdmi_phy {
|
||||||
|
struct clk *clk_phy;
|
||||||
|
struct clk *clk_pll0;
|
||||||
|
struct clk *clk_pll1;
|
||||||
|
+ struct device *dev;
|
||||||
|
unsigned int rcal;
|
||||||
|
struct regmap *regs;
|
||||||
|
struct reset_control *rst_phy;
|
||||||
|
@@ -205,7 +206,8 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
|
||||||
|
|
||||||
|
int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node);
|
||||||
|
|
||||||
|
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
|
||||||
|
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
|
||||||
|
+void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy);
|
||||||
|
void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
|
||||||
|
struct dw_hdmi_plat_data *plat_data);
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
|
||||||
|
index c9239708d398..78b152973957 100644
|
||||||
|
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
|
||||||
|
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
|
||||||
|
@@ -506,9 +506,60 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
|
||||||
|
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_deassert_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_deassert_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,
|
||||||
|
@@ -638,6 +689,7 @@ static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
phy->variant = (struct sun8i_hdmi_phy_variant *)match->data;
|
||||||
|
+ phy->dev = dev;
|
||||||
|
|
||||||
|
ret = of_address_to_resource(node, 0, &res);
|
||||||
|
if (ret) {
|
||||||
|
@@ -696,47 +748,10 @@ static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
|
||||||
|
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:
|
||||||
|
@@ -753,12 +768,6 @@ static int sun8i_hdmi_phy_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user