Genio 700 HDMI Signal Levels & Driving Strength

We are measuring the D0, D1, and D2 signals on a G700 EVK. The image is Yocto V24.1 (Downloaded from Download)

We found that when testing 720p60 and 1080p60, the D1 signal has a greater amplitude than D0 and D2 (as shown in the following figure, the green wave is D1).

However, we would expect that D0, D1, and D2 should have similar amplitudes. We know that there is a document “MTK_MT8390_HDMI Compliance Guide_v2.1.pptx” on the DDC website (Mediatek Account | Login) showing how to modify the D0, D1 and D2 strengths, but we did not modify anything. What might be the problem ?

Hi @rmyoshi,

Please apply the following diff and retry. A similar D0, D1, and D2 amplitudes should be seen.

The issue is that for the MT8390, the HDMITX impedance is calibrated, and the calibrated results are combined into a number, which is written into an unerasable location called the efuse.

The HDMITX PHY driver should read the number from the efuse and set the relative impedance settings into the HDMITX PHY registers. The V24.1 driver doesn’t do that, which is why you see the weird behavior.

After that, you may adjust the driving strength based on the calibrated impedance.

We will get back to you again after the formal solution is pushed to Gitlab.

diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
index 195b53577dd2..3e027742310f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
@@ -1409,6 +1409,8 @@ usb_host0: xhci@112b0000 {
 
 		hdmi_phy: hdmi-phy@11d5f000 {
 			compatible = "mediatek,mt8188-hdmi-phy";
+			nvmem-cells = <&hdmitx_efuse>;
+			nvmem-cell-names = "hdmitx_phy_efuse";
 			reg = <0 0x11d5f000 0 0x100>;
 			clocks = <&infracfg_ao CLK_INFRA_AO_HDMI_26M>;
 			clock-names = "pll_ref";
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
index b3c40c3e68a3..7260a631d5ce 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
@@ -119,7 +119,8 @@ static int mtk_hdmi_pll_performance_setting(struct clk_hw *hw)
 	 * This calibraion value is not board-dependent
 	 * so no SW adjustment required.
 	 */
-	if (hdmi_phy->conf->efuse_sw_mode) {
+
+	if ((hdmi_phy->efuse == 0) || (hdmi_phy->conf->efuse_sw_mode == true)) {
 		dev_info(hdmi_phy->dev, "efuse_sw_mode ENABLED!!!");
 		mtk_hdmi_phy_mask(hdmi_phy, HDMI_CTL_1,
 				0x1f << RG_INTR_IMP_RG_MODE_SHIFT,
@@ -501,26 +502,44 @@ static int mtk_hdmi_pll_drv_setting(struct clk_hw *hw)
 	mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_0,
 			  impedance_en << RG_HDMITX21_DRV_IMP_EN_SHIFT,
 			  RG_HDMITX21_DRV_IMP_EN);
-	mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
-			  impedance << RG_HDMITX21_DRV_IMP_D0_EN1_SHIFT,
-			  RG_HDMITX21_DRV_IMP_D0_EN1);
-	mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
-			  impedance << RG_HDMITX21_DRV_IMP_D1_EN1_SHIFT,
-			  RG_HDMITX21_DRV_IMP_D1_EN1);
-	mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
-			  impedance << RG_HDMITX21_DRV_IMP_D2_EN1_SHIFT,
-			  RG_HDMITX21_DRV_IMP_D2_EN1);
-	mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
-			  impedance << RG_HDMITX21_DRV_IMP_CLK_EN1_SHIFT,
-			  RG_HDMITX21_DRV_IMP_CLK_EN1);
-
-	/* calibration */
-	if (hdmi_phy->conf->efuse_sw_mode) {
-		/* default SW calibration setting suggested */
-		calibration = 0x11;
+
+	if (hdmi_phy->efuse == 0) {
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_D0_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_D0_EN1);
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_D1_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_D1_EN1);
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_D2_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_D2_EN1);
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_CLK_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_CLK_EN1);
 		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_6,
-				calibration << RG_HDMITX21_INTR_CAL_SHIFT,
-				RG_HDMITX21_INTR_CAL);
+			0x11 << RG_HDMITX21_INTR_CAL_SHIFT,
+			RG_HDMITX21_INTR_CAL);
+	} else if (hdmi_phy->conf->efuse_sw_mode == true) {
+		impedance = hdmi_phy->efuse & 0x3f;
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_D0_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_D0_EN1);
+		impedance = (hdmi_phy->efuse >> 6) & 0x3f;
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_D1_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_D1_EN1);
+		impedance = (hdmi_phy->efuse >> 12) & 0x3f;
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_D2_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_D2_EN1);
+		impedance = (hdmi_phy->efuse >> 18) & 0x3f;
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_2,
+			impedance << RG_HDMITX21_DRV_IMP_CLK_EN1_SHIFT,
+			RG_HDMITX21_DRV_IMP_CLK_EN1);
+		calibration = (hdmi_phy->efuse >> 24) & 0x1f;
+		mtk_hdmi_phy_mask(hdmi_phy, HDMI_1_CFG_6,
+			calibration << RG_HDMITX21_INTR_CAL_SHIFT,
+			RG_HDMITX21_INTR_CAL);
 	}
 
 	return 0;
@@ -728,6 +747,21 @@ struct mtk_hdmi_phy_conf mtk_hdmi_phy_8195_conf = {
 	.power_control = mtk_hdmi_power_control,
 };
 
+struct mtk_hdmi_phy_conf mtk_hdmi_phy_8188_conf = {
+	/* TODO: CLK_SET_RATE_GATE causes hdmi_txpll clock
+	 * set_rate() fails. We need to adjust client
+	 * calling sequences to properly address this issue.
+	 */
+	.flags = CLK_SET_RATE_PARENT,
+	.hdmi_phy_clk_ops = &mtk_hdmi_pll_ops,
+	.hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
+	.hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
+	.hdmi_phy_configure = mtk_hdmi_phy_configure,
+	.efuse_sw_mode = true,
+	.power_control = mtk_hdmi_power_control,
+};
+
+
 MODULE_AUTHOR("Can Zeng <can.zeng@mediatek.com>");
 MODULE_DESCRIPTION("MediaTek MT8195 HDMI PHY Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c
index e6e448c24c10..0e51cf83fcca 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi.c
@@ -5,6 +5,7 @@
  */
 
 #include "phy-mtk-hdmi.h"
+#include <linux/nvmem-consumer.h>
 
 static int mtk_hdmi_phy_power_on(struct phy *phy);
 static int mtk_hdmi_phy_power_off(struct phy *phy);
@@ -121,6 +122,10 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
 
 	struct phy *phy;
 	struct phy_provider *phy_provider;
+
+	struct nvmem_cell *cell;
+	unsigned int *efuse_buffer;
+	size_t len;
 	int ret;
 
 	hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
@@ -173,6 +178,18 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	cell = nvmem_cell_get(dev, "hdmitx_phy_efuse");
+	if (IS_ERR(cell)) {
+		dev_err(&pdev->dev,"failed to read efuse\n");
+		hdmi_phy->efuse = 0;
+	} else {
+		efuse_buffer = (unsigned int *)nvmem_cell_read(cell, &len);
+		nvmem_cell_put(cell);
+		hdmi_phy->efuse = *efuse_buffer;//hdmitx efuse only 4 bytes
+		kfree((u8 *)efuse_buffer);
+		pr_notice("efuse=0x%x\n", hdmi_phy->efuse);
+	}
+
 	dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
 	hdmi_phy->drv_imp_clk = 0x30;
 	hdmi_phy->drv_imp_d2 = 0x30;
@@ -238,7 +255,7 @@ static const struct of_device_id mtk_hdmi_phy_match[] = {
 	  .data = &mtk_hdmi_phy_8195_conf,
 	},
 	{ .compatible = "mediatek,mt8188-hdmi-phy",
-	  .data = &mtk_hdmi_phy_8195_conf,
+	  .data = &mtk_hdmi_phy_8188_conf,
 	},
 	{},
 };
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.h b/drivers/phy/mediatek/phy-mtk-hdmi.h
index a752a088a6b4..e694df6f3d73 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi.h
+++ b/drivers/phy/mediatek/phy-mtk-hdmi.h
@@ -44,6 +44,7 @@ struct mtk_hdmi_phy {
 	unsigned int ibias;
 	unsigned int ibias_up;
 	bool is_over_340M;
+	unsigned int efuse;
 };
 
 void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
@@ -55,6 +56,7 @@ void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
 struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
 
 extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8195_conf;
+extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8188_conf;
 extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
 extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf;