drm: bridge: synopsys: dw-hdmi: Enable LicheePi 4A dw-hdmi modifications 86/311586/3
authorMichal Wilczynski <m.wilczynski@samsung.com>
Mon, 27 May 2024 13:04:59 +0000 (15:04 +0200)
committerMichal Wilczynski <m.wilczynski@samsung.com>
Mon, 27 May 2024 13:06:34 +0000 (15:06 +0200)
Unfortunately, besides adding it's own hdmi driver LicheePi4 also
need some modifications to generic dw-hdmi driver. Enable them.

Change-Id: I5c49d46fed5a8c1b57863404438ef0f1ff25d883
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
include/drm/bridge/dw_hdmi.h

index 6c1d7947450545916befc09ce2fc3127d9654c99..4bd164202966e22f4d86a250cc394bccac36c860 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
@@ -140,6 +141,8 @@ struct dw_hdmi {
        struct clk *isfr_clk;
        struct clk *iahb_clk;
        struct clk *cec_clk;
+       struct clk *pix_clk;
+       struct clk *i2s_clk;
        struct dw_hdmi_i2c *i2c;
 
        struct hdmi_data_info hdmi_data;
@@ -676,10 +679,12 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
                cts = 0;
        }
 
+       hdmi->audio_enable = true;
        spin_lock_irq(&hdmi->audio_lock);
        hdmi->audio_n = n;
        hdmi->audio_cts = cts;
        hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
+       hdmi_writeb(hdmi, 0x4, HDMI_AUD_INPUTCLKFS);
        spin_unlock_irq(&hdmi->audio_lock);
 }
 
@@ -2096,6 +2101,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
                         * Source Devices compliant shall set the
                         * Source Version = 1.
                         */
+                       mdelay(60);
                        drm_scdc_readb(hdmi->ddc, SCDC_SINK_VERSION,
                                       &bytes);
                        drm_scdc_writeb(hdmi->ddc, SCDC_SOURCE_VERSION,
@@ -2166,6 +2172,7 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
        hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
 
        /* Enable pixel clock and tmds data path */
+#if 0
        hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE |
                           HDMI_MC_CLKDIS_CSCCLK_DISABLE |
                           HDMI_MC_CLKDIS_AUDCLK_DISABLE |
@@ -2191,6 +2198,7 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
                hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
                            HDMI_MC_FLOWCTRL);
        }
+#endif
 }
 
 /* Workaround to clear the overflow condition */
@@ -2952,6 +2960,7 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
        dw_hdmi_update_phy_mask(hdmi);
        handle_plugged_change(hdmi, false);
        mutex_unlock(&hdmi->mutex);
+       pm_runtime_put(hdmi->dev);
 }
 
 static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
@@ -2964,6 +2973,7 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
        connector = drm_atomic_get_new_connector_for_encoder(state,
                                                             bridge->encoder);
 
+       pm_runtime_get_sync(hdmi->dev);
        mutex_lock(&hdmi->mutex);
        hdmi->disabled = false;
        hdmi->curr_conn = connector;
@@ -3362,7 +3372,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
        hdmi->disabled = true;
        hdmi->rxsense = true;
        hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
-       hdmi->mc_clkdis = 0x7f;
+       hdmi->mc_clkdis = 0x0;
        hdmi->last_connector_result = connector_status_disconnected;
 
        mutex_init(&hdmi->mutex);
@@ -3467,6 +3477,20 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
                }
        }
 
+       hdmi->pix_clk = devm_clk_get(hdmi->dev, "pixclk");
+       if (IS_ERR(hdmi->pix_clk)) {
+               ret = PTR_ERR(hdmi->pix_clk);
+               dev_err(hdmi->dev, "Unable to get HDMI pix clk: %d\n", ret);
+               goto err_iahb;
+       }
+
+       hdmi->i2s_clk = devm_clk_get_optional(hdmi->dev, "i2s");
+       if (IS_ERR(hdmi->i2s_clk)) {
+               ret = PTR_ERR(hdmi->i2s_clk);
+               dev_err(hdmi->dev, "Unable to get HDMI i2s clk: %d\n", ret);
+               goto err_iahb;
+       }
+
        /* Product and revision IDs */
        hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
                      | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
@@ -3691,6 +3715,24 @@ void dw_hdmi_resume(struct dw_hdmi *hdmi)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_resume);
 
+#ifdef CONFIG_PM
+int dw_hdmi_runtime_suspend(struct dw_hdmi *hdmi)
+{
+       clk_disable_unprepare(hdmi->pix_clk);
+       clk_disable_unprepare(hdmi->cec_clk);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_runtime_suspend);
+
+int dw_hdmi_runtime_resume(struct dw_hdmi *hdmi)
+{
+       clk_prepare_enable(hdmi->cec_clk);
+       clk_prepare_enable(hdmi->pix_clk);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_runtime_resume);
+#endif
+
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
index 6a46baa0737cd082927bb85afe9cf3434969a24b..30de0e07c2ebe0bf9df9cd9e350cf502e35816ae 100644 (file)
@@ -174,6 +174,11 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
 
 void dw_hdmi_resume(struct dw_hdmi *hdmi);
 
+#ifdef CONFIG_PM
+int dw_hdmi_runtime_suspend(struct dw_hdmi *hdmi);
+int dw_hdmi_runtime_resume(struct dw_hdmi *hdmi);
+#endif
+
 void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense);
 
 int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,