Browse Source

uboot: hdmi logo causes kernel hdmi unstable

The hdmi display is unstable after repeated reset
blank panel or write panel

Signed-off-by: Keith Zhao <keith.zhao@starfivetech.com>
Keith Zhao 9 months ago
parent
commit
26a31fa6bc

+ 3 - 7
drivers/power/domain/starfive-power-domain.c

@@ -68,9 +68,7 @@ static int sf_power_domain_on(struct power_domain *power_domain)
 	encourage_hi = SW_MODE_ENCOURAGE_EN_HI;
 
 	/* write SW_ENCOURAGE to make the configuration take effect */
-	val = __raw_readl(priv->regs + mode) | BIT(power_domain->id);
-
-	__raw_writel(val, priv->regs + mode);
+	__raw_writel(BIT(power_domain->id), priv->regs + mode);
 	__raw_writel(SW_MODE_ENCOURAGE_ON, priv->regs + SW_ENCOURAGE);
 	__raw_writel(encourage_lo, priv->regs + SW_ENCOURAGE);
 	__raw_writel(encourage_hi, priv->regs + SW_ENCOURAGE);
@@ -99,9 +97,7 @@ static int sf_power_domain_off(struct power_domain *power_domain)
 	encourage_lo = SW_MODE_ENCOURAGE_DIS_LO;
 	encourage_hi = SW_MODE_ENCOURAGE_DIS_HI;
 
-	val = __raw_readl(priv->regs + mode) & ~(BIT(power_domain->id));
-
-	__raw_writel(val, priv->regs + mode);
+	__raw_writel(BIT(power_domain->id), priv->regs + mode);
 	__raw_writel(SW_MODE_ENCOURAGE_ON, priv->regs + SW_ENCOURAGE);
 	__raw_writel(encourage_lo, priv->regs + SW_ENCOURAGE);
 	__raw_writel(encourage_hi, priv->regs + SW_ENCOURAGE);
@@ -110,7 +106,7 @@ static int sf_power_domain_off(struct power_domain *power_domain)
 					!(val & BIT(power_domain->id)),
 					TIMEOUT_US);
 	if (ret) {
-		pr_err("power_off failed");
+		pr_err("power_off failed\n");
 		return -ETIMEDOUT;
 	}
 

+ 21 - 0
drivers/video/starfive/sf_hdmi.c

@@ -540,6 +540,25 @@ free_clock_sys_clk:
 
 }
 
+static int sf_hdmi_remove(struct udevice *dev)
+{
+	struct sf_hdmi_priv *priv = dev_get_priv(dev);
+	debug("sf_hdmi_remove  ---\n");
+	hdmi_write(priv, 0x00,0x1b2);
+	hdmi_write(priv, 0x00,0x1be);
+	hdmi_write(priv, 0x00,0x1b4);
+	hdmi_write(priv, 1,0x1a0);
+	hdmi_write(priv, 1,0x1aa);
+	hdmi_write(priv, 0x00,0x1cc);
+	hdmi_write(priv, 0x00,0x1b0);
+
+	clk_disable(&priv->bclk);
+	clk_disable(&priv->mclk);
+	clk_disable(&priv->sys_clk);
+	reset_assert(&priv->tx_rst);
+	return 0;
+}
+
 static const struct dm_display_ops inno_hdmi_ops = {
 	.read_edid = rk_hdmi_read_edid,
 	.enable = inno_hdmi_enable,
@@ -558,4 +577,6 @@ U_BOOT_DRIVER(inno_hdmi_starfive) = {
 	.of_to_plat = inno_hdmi_of_to_plat,
 	.probe = inno_hdmi_probe,
 	.priv_auto	= sizeof(struct sf_hdmi_priv),
+	.remove = sf_hdmi_remove,
+	.flags = DM_FLAG_OS_PREPARE,
 };

+ 146 - 1
drivers/video/starfive/sf_vop.c

@@ -32,6 +32,47 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static void iotrace_writel(ulong value, void *ptr)
+{
+	//printf("writel( 0x%08x, %p ) -- 0x%08x\n", value, ptr, readl(ptr));
+	//readl(ptr);
+	mdelay(10);
+	writel(value, ptr);
+}
+
+static int sf_vop_power_off(struct udevice *dev)
+{
+	struct udevice *dev_power;
+	struct udevice *dev_pmic;
+	struct power_domain_ops *ops;
+	struct power_domain power_domain;
+	int ret;
+	if (!(gd->flags & GD_FLG_RELOC))
+		 return 0;
+	ret = uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev_power);
+	if (ret)
+		return ret;
+
+	ret = device_probe(dev_power);
+	if (ret) {
+		pr_err("%s: device '%s' display won't probe (ret=%d)\n",
+		   __func__, dev_power->name, ret);
+		return ret;
+	}
+
+	ops = (struct power_domain_ops *)dev_power->driver->ops;
+	power_domain.dev = dev_power;
+	power_domain.id = 4;
+
+	ret = ops->off(&power_domain);
+	if (ret) {
+		pr_err("ops->0ff() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int sf_vop_power(struct udevice *dev)
 {
 	struct udevice *dev_power;
@@ -83,6 +124,7 @@ static int sf_vop_power(struct udevice *dev)
 	return 0;
 }
 
+
 static int vout_get_rst_clock_resources(struct udevice *dev)
 {
 	struct sf_vop_priv *priv = dev_get_priv(dev);
@@ -120,7 +162,7 @@ static int vout_get_rst_clock_resources(struct udevice *dev)
 
 	ret = clk_get_by_name(dev, "dc_pix1", &priv->dc_pix1);
 	if (ret) {
-		pr_err("clk_get_by_name(dc_pix0) failed: %d\n", ret);
+		pr_err("clk_get_by_name(dc_pix1) failed: %d\n", ret);
 		return ret;
 	}
 
@@ -509,6 +551,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 		writel(0x00000000, priv->regs_hi+0x000024fc);
 		writel(0x00000c24, priv->regs_hi+0x000024e8);
 		writel(0x00000001, priv->regs_hi+0x00001ccc);
+		priv->hdmi_logo = true;
 		return 0;
 	}
 
@@ -617,6 +660,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 		writel(0x00000000, priv->regs_hi+0x000024fc); //csr_reg
 		writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
 		writel(0x00000001, priv->regs_hi+0x00001ccc); //csr_reg
+		priv->mipi_logo = true;
 		return 0;
 	}
 
@@ -641,6 +685,8 @@ static int sf_vop_probe(struct udevice *dev)
 	priv->regs_low = dev_remap_addr_name(dev, "low");
 	if (!priv->regs_low)
 		return -EINVAL;
+	priv->hdmi_logo = false;
+	priv->mipi_logo = false;
 
 	vout_probe_resources_jh7110(dev);
 
@@ -667,6 +713,104 @@ static int sf_vop_probe(struct udevice *dev)
 
 static int sf_vop_remove(struct udevice *dev)
 {
+	struct sf_vop_priv *priv = dev_get_priv(dev);
+	debug("sf_vop_remove-------\n");
+	int ret;
+
+	if(priv->mipi_logo == true)
+		return 0;
+
+	if(priv->hdmi_logo == false)
+		return 0;
+
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1cc0 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x24e0 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1810 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1400 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1408 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1ce8 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2510 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2508 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2500 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1518 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1540 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2540 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1544 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2544 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1548 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2548 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x154c );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x254c );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x2518 );
+	iotrace_writel( 0x00000e07, priv->regs_hi+0x1a28 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1430 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1438 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1440 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1448 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x14b0 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1cd0 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x14b8 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x14d0 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1528 );
+	iotrace_writel( 0x00000100, priv->regs_hi+0x1418 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1410 );
+	iotrace_writel( 0x00000001, priv->regs_hi+0x2518 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1468 );
+	iotrace_writel( 0x00000001, priv->regs_hi+0x1484 );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x24e8 );
+	iotrace_writel( 0x00000001, priv->regs_hi+0x24fc );
+	iotrace_writel( 0x00000000, priv->regs_hi+0x1ccc );
+
+	ret = reset_assert(&priv->dc8200_rst_axi);
+	if (ret) {
+		pr_err("failed to assert dc8200_rst_axi reset (ret=%d)\n", ret);
+		return ret;
+	}
+
+	ret = reset_assert(&priv->dc8200_rst_core);
+	if (ret) {
+		pr_err("failed to assert dc8200_rst_axi reset (ret=%d)\n", ret);
+		return ret;
+	}
+
+	ret = reset_assert(&priv->dc8200_rst_ahb);
+	if (ret) {
+		pr_err("failed to assert dc8200_rst_ahb reset (ret=%d)\n", ret);
+		return ret;
+	}
+
+	clk_set_rate(&priv->dc_pix_src, 74250000);
+
+	clk_disable(&priv->hdmitx0_pixelclk);
+
+	clk_disable(&priv->dc_ahb);
+
+	clk_disable(&priv->dc_core);
+
+	clk_disable(&priv->dc_axi);
+
+	clk_disable(&priv->dc_pix1);
+
+	clk_disable(&priv->dc_pix0);
+
+	ret = reset_assert(&priv->rst_vout_src);
+	if (ret) {
+		pr_err("failed to deassert rst_vout_src reset (ret=%d)\n", ret);
+		return ret;
+	}
+
+	clk_disable(&priv->top_vout_ahb);
+
+	clk_disable(&priv->top_vout_axi);
+
+	clk_disable(&priv->vout_src);
+
+	clk_disable(&priv->disp_axi);
+
+	reset_assert(&priv->noc_disp);
+
+	sf_vop_power_off(dev);
+
 	return 0;
 }
 
@@ -703,4 +847,5 @@ U_BOOT_DRIVER(starfive_dc8200) = {
 	.probe	= sf_vop_probe,
     .remove = sf_vop_remove,
 	.priv_auto	= sizeof(struct sf_vop_priv),
+	.flags = DM_FLAG_OS_PREPARE,
 };

+ 2 - 0
drivers/video/starfive/sf_vop.h

@@ -66,6 +66,8 @@ struct sf_vop_priv {
 
 	struct reset_ctl rst_vout_src;
 	struct reset_ctl noc_disp;
+	bool   mipi_logo;
+	bool   hdmi_logo;
 };
 
 enum vop_features {