Merge pull request #5751 from jernejsk/h3-cec-fix

[LE11] Allwinner: H3: linux: Fix SW CEC
This commit is contained in:
Christian Hewitt 2021-10-12 06:05:08 +04:00 committed by GitHub
commit bb67729b56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,21 +1,23 @@
From 0981ac8f42983c820790b14668d59f39b0375d90 Mon Sep 17 00:00:00 2001 From 411f022496f0f9715ca3dc9296f5823cbc0c867c Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net> From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sat, 25 May 2019 12:03:39 +0200 Date: Mon, 11 Oct 2021 20:13:41 +0200
Subject: [PATCH] HACK: SW CEC implementation for H3 Subject: [PATCH] HACK: SW CEC implementation for H3
Many H3 boards lack 32768 Hz external oscillator, so internal RC is used Many H3 boards lack 32768 Hz external oscillator, so internal RC is used
instead. However, it's too unstable for CEC. Use SW implementation instead. However, it's too unstable for CEC. Use SW implementation
instead. That makes it usable, albeit sensitive to cpufreq changes. instead. That makes it usable, albeit sensitive to cpufreq changes.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
--- ---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +-
drivers/gpu/drm/sun4i/Kconfig | 2 + drivers/gpu/drm/sun4i/Kconfig | 2 +
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 12 ++++ drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 12 ++++
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 74 ++++++++++++++++++++++- drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 76 ++++++++++++++++++++++-
include/drm/bridge/dw_hdmi.h | 2 + include/drm/bridge/dw_hdmi.h | 2 +
5 files changed, 89 insertions(+), 3 deletions(-) 5 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5755f0432e77..b93eb2fb52ce 100644
--- a/drivers/gpu/drm/sun4i/Kconfig --- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -56,6 +56,8 @@ config DRM_SUN8I_DW_HDMI @@ -56,6 +56,8 @@ config DRM_SUN8I_DW_HDMI
@ -27,6 +29,8 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
help help
Choose this option if you have an Allwinner SoC with the Choose this option if you have an Allwinner SoC with the
DesignWare HDMI controller with custom HDMI PHY. If M is DesignWare HDMI controller with custom HDMI PHY. If M is
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index bffe1b9cd3dc..438f7398e26d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
@ -69,9 +73,11 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
struct clk *clk_bus; struct clk *clk_bus;
struct clk *clk_mod; struct clk *clk_mod;
struct clk *clk_phy; struct clk *clk_phy;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 78b152973957..0d87b56b700a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -498,8 +498,9 @@ static void sun8i_hdmi_phy_init_h3(struc @@ -498,8 +498,9 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0); SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0);
@ -83,7 +89,7 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
/* read calibration data */ /* read calibration data */
regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val);
@@ -525,8 +526,47 @@ void sun8i_hdmi_phy_set_ops(struct sun8i @@ -576,8 +577,47 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
plat_data->cur_ctr = variant->cur_ctr; plat_data->cur_ctr = variant->cur_ctr;
plat_data->phy_config = variant->phy_cfg; plat_data->phy_config = variant->phy_cfg;
} }
@ -131,7 +137,7 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
static const struct regmap_config sun8i_hdmi_phy_regmap_config = { static const struct regmap_config sun8i_hdmi_phy_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
@@ -543,6 +583,7 @@ static const struct sun8i_hdmi_phy_varia @@ -594,6 +634,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
}; };
static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = { static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
@ -139,10 +145,19 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
.has_phy_clk = true, .has_phy_clk = true,
.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 @@ -653,6 +694,7 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
goto err_put_clk_pll1; {
} struct platform_device *pdev = of_find_device_by_node(node);
struct sun8i_hdmi_phy *phy;
+ int ret;
if (!pdev)
return -EPROBE_DEFER;
@@ -664,8 +706,35 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
hdmi->phy = phy;
put_device(&pdev->dev);
+
+ if (phy->variant->bit_bang_cec) { + if (phy->variant->bit_bang_cec) {
+ phy->cec_adapter = + phy->cec_adapter =
+ cec_pin_allocate_adapter(&sun8i_hdmi_phy_cec_pin_ops, + cec_pin_allocate_adapter(&sun8i_hdmi_phy_cec_pin_ops,
@ -150,33 +165,31 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
+ CEC_CAP_DEFAULTS); + CEC_CAP_DEFAULTS);
+ ret = PTR_ERR_OR_ZERO(phy->cec_adapter); + ret = PTR_ERR_OR_ZERO(phy->cec_adapter);
+ if (ret < 0) + if (ret < 0)
+ goto err_disable_clk_phy; + return 0;
+ +
+ phy->cec_notifier = cec_notifier_cec_adap_register(dev, NULL, phy->cec_adapter); + phy->cec_notifier = cec_notifier_cec_adap_register(hdmi->dev, NULL, phy->cec_adapter);
+ if (!phy->cec_notifier) { + if (!phy->cec_notifier) {
+ ret = -ENOMEM; + ret = -ENOMEM;
+ goto err_delete_cec_adapter; + goto err_delete_cec_adapter;
+ } + }
+ +
+ ret = cec_register_adapter(phy->cec_adapter, dev); + ret = cec_register_adapter(phy->cec_adapter, hdmi->dev);
+ if (ret < 0) + if (ret < 0)
+ goto err_put_cec_notifier; + goto err_put_cec_notifier;
+ } + }
+
platform_set_drvdata(pdev, phy);
return 0; return 0;
+
+err_put_cec_notifier: +err_put_cec_notifier:
+ cec_notifier_cec_adap_unregister(phy->cec_notifier, phy->cec_adapter); + cec_notifier_cec_adap_unregister(phy->cec_notifier, phy->cec_adapter);
+err_delete_cec_adapter: +err_delete_cec_adapter:
+ cec_delete_adapter(phy->cec_adapter); + cec_delete_adapter(phy->cec_adapter);
+err_disable_clk_phy: +
+ clk_disable_unprepare(phy->clk_phy); + return ret;
err_put_clk_pll1: }
clk_put(phy->clk_pll1);
err_put_clk_pll0: static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
@@ -753,6 +820,9 @@ static int sun8i_hdmi_phy_remove(struct @@ -768,6 +837,9 @@ static int sun8i_hdmi_phy_remove(struct platform_device *pdev)
{ {
struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev); struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);