From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 03:04:41 +0000 Subject: [PATCH] rk3568 rt init --- kernel/drivers/gpu/drm/rockchip/inno_hdmi.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 97 insertions(+), 19 deletions(-) diff --git a/kernel/drivers/gpu/drm/rockchip/inno_hdmi.c b/kernel/drivers/gpu/drm/rockchip/inno_hdmi.c index c9a51ae..87eebd7 100644 --- a/kernel/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/kernel/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -55,11 +55,28 @@ struct completion cmp; }; +enum inno_hdmi_dev_type { + RK3036_HDMI, + RK3128_HDMI, +}; + +struct inno_hdmi_phy_config { + unsigned long mpixelclock; + u8 pre_emphasis; /* pre-emphasis value */ + u8 vlev_ctr; /* voltage level control */ +}; + +struct inno_hdmi_plat_data { + enum inno_hdmi_dev_type dev_type; + struct inno_hdmi_phy_config *phy_config; +}; + struct inno_hdmi { struct device *dev; struct drm_device *drm_dev; int irq; + struct clk *aclk; struct clk *pclk; void __iomem *regs; @@ -70,6 +87,7 @@ struct i2c_adapter *ddc; unsigned int tmds_rate; + const struct inno_hdmi_plat_data *plat_data; struct hdmi_data_info hdmi_data; struct drm_display_mode previous_mode; @@ -197,12 +215,20 @@ static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) { + const struct inno_hdmi_phy_config *phy_config = + hdmi->plat_data->phy_config; + switch (mode) { case NORMAL: inno_hdmi_sys_power(hdmi, false); - - hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); - hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); + for (; phy_config->mpixelclock != ~0UL; phy_config++) + if (hdmi->tmds_rate <= phy_config->mpixelclock) + break; + if (!phy_config->mpixelclock) + return; + hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, + phy_config->pre_emphasis); + hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->vlev_ctr); hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14); @@ -389,6 +415,12 @@ { int value; + if (hdmi->plat_data->dev_type == RK3036_HDMI) { + value = BIT(20) | BIT(21); + value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0; + value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0; + hdmi_writeb(hdmi, 0x148, value); + } /* Set detail external video timing polarity and interlace mode */ value = v_EXTERANL_VIDEO(1); value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? @@ -823,6 +855,41 @@ return adap; } +static struct inno_hdmi_phy_config rk3036_hdmi_phy_config[] = { + /* pixelclk pre-emp vlev */ + { 74250000, 0x3f, 0xbb }, + { 165000000, 0x6f, 0xbb }, + { ~0UL, 0x00, 0x00 } +}; + +static struct inno_hdmi_phy_config rk3128_hdmi_phy_config[] = { + /* pixelclk pre-emp vlev */ + { 74250000, 0x3f, 0xaa }, + { 165000000, 0x5f, 0xaa }, + { ~0UL, 0x00, 0x00 } +}; + +static const struct inno_hdmi_plat_data rk3036_hdmi_drv_data = { + .dev_type = RK3036_HDMI, + .phy_config = rk3036_hdmi_phy_config, +}; + +static const struct inno_hdmi_plat_data rk3128_hdmi_drv_data = { + .dev_type = RK3128_HDMI, + .phy_config = rk3128_hdmi_phy_config, +}; + +static const struct of_device_id inno_hdmi_dt_ids[] = { + { .compatible = "rockchip,rk3036-inno-hdmi", + .data = &rk3036_hdmi_drv_data, + }, + { .compatible = "rockchip,rk3128-inno-hdmi", + .data = &rk3128_hdmi_drv_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids); + static int inno_hdmi_bind(struct device *dev, struct device *master, void *data) { @@ -839,11 +906,22 @@ hdmi->dev = dev; hdmi->drm_dev = drm; + hdmi->plat_data = device_get_match_data(hdmi->dev); iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); hdmi->regs = devm_ioremap_resource(dev, iores); if (IS_ERR(hdmi->regs)) return PTR_ERR(hdmi->regs); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + hdmi->aclk = devm_clk_get(hdmi->dev, "aclk"); + if (IS_ERR(hdmi->aclk)) { + dev_err(hdmi->dev, "Unable to get HDMI aclk clk\n"); + return PTR_ERR(hdmi->aclk); + } hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); if (IS_ERR(hdmi->pclk)) { @@ -851,17 +929,17 @@ return PTR_ERR(hdmi->pclk); } - ret = clk_prepare_enable(hdmi->pclk); + ret = clk_prepare_enable(hdmi->aclk); if (ret) { DRM_DEV_ERROR(hdmi->dev, - "Cannot enable HDMI pclk clock: %d\n", ret); + "Cannot enable HDMI aclk clock: %d\n", ret); return ret; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - goto err_disable_clk; + ret = clk_prepare_enable(hdmi->pclk); + if (ret) { + dev_err(hdmi->dev, "Cannot enable HDMI pclk clock: %d\n", ret); + goto err_disable_aclk; } inno_hdmi_reset(hdmi); @@ -870,7 +948,7 @@ if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - goto err_disable_clk; + goto err_disable_pclk; } /* @@ -894,17 +972,23 @@ ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); - if (ret < 0) + if (ret) { + dev_err(hdmi->dev, + "failed to request hdmi irq: %d\n", ret); goto err_cleanup_hdmi; + } return 0; + err_cleanup_hdmi: hdmi->connector.funcs->destroy(&hdmi->connector); hdmi->encoder.funcs->destroy(&hdmi->encoder); err_put_adapter: i2c_put_adapter(hdmi->ddc); -err_disable_clk: +err_disable_pclk: clk_disable_unprepare(hdmi->pclk); +err_disable_aclk: + clk_disable_unprepare(hdmi->aclk); return ret; } @@ -918,6 +1002,7 @@ i2c_put_adapter(hdmi->ddc); clk_disable_unprepare(hdmi->pclk); + clk_disable_unprepare(hdmi->aclk); } static const struct component_ops inno_hdmi_ops = { @@ -936,13 +1021,6 @@ return 0; } - -static const struct of_device_id inno_hdmi_dt_ids[] = { - { .compatible = "rockchip,rk3036-inno-hdmi", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids); struct platform_driver inno_hdmi_driver = { .probe = inno_hdmi_probe, -- Gitblit v1.6.2