From 06e912bd821b21d9360a75cde2d78b03f17a5872 Mon Sep 17 00:00:00 2001 From: Wen He Date: Tue, 17 Sep 2019 15:35:52 +0800 Subject: [PATCH] drm: ls1028a: Add DP driver support for LS1028A Add Display Port driver support for NXP Layerscape LS1028A platform. Signed-off-by: Wen He --- drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 1 + drivers/gpu/drm/imx/Makefile | 2 +- drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c | 13 +++ drivers/gpu/drm/imx/cdn-mhdp-ls1028a.c | 110 ++++++++++++++++++++++++++ drivers/gpu/drm/imx/cdns-mhdp-imx.h | 2 + 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/imx/cdn-mhdp-ls1028a.c --- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c @@ -275,6 +275,7 @@ static int cdns_dp_bridge_attach(struct struct drm_connector *connector = &mhdp->connector.base; connector->interlace_allowed = 1; + connector->polled = DRM_CONNECTOR_POLL_HPD; drm_connector_helper_add(connector, &cdns_dp_connector_helper_funcs); --- a/drivers/gpu/drm/imx/Makefile +++ b/drivers/gpu/drm/imx/Makefile @@ -9,4 +9,4 @@ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o -obj-$(CONFIG_DRM_IMX_CDNS_MHDP) += cdn-mhdp-imxdrv.o cdn-mhdp-dp-phy.o cdn-mhdp-hdmi-phy.o cdn-mhdp-imx8qm.o +obj-$(CONFIG_DRM_IMX_CDNS_MHDP) += cdn-mhdp-imxdrv.o cdn-mhdp-dp-phy.o cdn-mhdp-hdmi-phy.o cdn-mhdp-imx8qm.o cdn-mhdp-ls1028a.o --- a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c +++ b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c @@ -94,6 +94,16 @@ static struct cdns_plat_data imx8qm_dp_d .is_dp = true, }; +static struct cdns_plat_data ls1028a_dp_drv_data = { + .bind = cdns_dp_bind, + .unbind = cdns_dp_unbind, + .phy_set = cdns_dp_phy_set_imx8mq, + .power_on = cdns_mhdp_power_on_ls1028a, + .firmware_init = cdns_mhdp_firmware_init_imx8qm, + .pclk_rate = cdns_mhdp_pclk_rate_ls1028a, + .bus_type = BUS_TYPE_NORMAL_APB, +}; + static const struct of_device_id cdns_mhdp_imx_dt_ids[] = { { .compatible = "cdn,imx8mq-hdmi", .data = &imx8mq_hdmi_drv_data @@ -107,6 +117,9 @@ static const struct of_device_id cdns_mh { .compatible = "cdn,imx8qm-dp", .data = &imx8qm_dp_drv_data }, + { .compatible = "cdn,ls1028a-dp", + .data = &ls1028a_dp_drv_data + }, {}, }; MODULE_DEVICE_TABLE(of, cdns_mhdp_imx_dt_ids); --- /dev/null +++ b/drivers/gpu/drm/imx/cdn-mhdp-ls1028a.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP + * + */ +#include +#include +#include +#include +#include + +#include "cdns-mhdp-imx.h" + +static const struct of_device_id scfg_device_ids[] = { + { .compatible = "fsl,ls1028a-scfg", }, + {} +}; + +static void ls1028a_phy_reset(u8 reset) +{ + struct device_node *scfg_node; + void __iomem *scfg_base = NULL; + + scfg_node = of_find_matching_node(NULL, scfg_device_ids); + if (scfg_node) + scfg_base = of_iomap(scfg_node, 0); + + iowrite32(reset, scfg_base + 0x230); +} + +int ls1028a_clocks_init(struct imx_mhdp_device *imx_mhdp) +{ + struct device *dev = imx_mhdp->mhdp.dev; + struct imx_hdp_clks *clks = &imx_mhdp->clks; + + clks->clk_core = devm_clk_get(dev, "clk_core"); + if (IS_ERR(clks->clk_core)) { + dev_warn(dev, "failed to get hdp core clk\n"); + return PTR_ERR(clks->clk_core); + } + + clks->clk_pxl = devm_clk_get(dev, "clk_pxl"); + if (IS_ERR(clks->clk_pxl)) { + dev_warn(dev, "failed to get pxl clk\n"); + return PTR_ERR(clks->clk_pxl); + } + + return true; +} + +static int ls1028a_pixel_clk_enable(struct imx_mhdp_device *imx_mhdp) +{ + struct imx_hdp_clks *clks = &imx_mhdp->clks; + struct device *dev = imx_mhdp->mhdp.dev; + int ret; + + ret = clk_prepare_enable(clks->clk_pxl); + if (ret < 0) { + dev_err(dev, "%s, pre clk pxl error\n", __func__); + return ret; + } + + return ret; +} + +static void ls1028a_pixel_clk_disable(struct imx_mhdp_device *imx_mhdp) +{ + struct imx_hdp_clks *clks = &imx_mhdp->clks; + + clk_disable_unprepare(clks->clk_pxl); +} + +static void ls1028a_pixel_clk_set_rate(struct imx_mhdp_device *imx_mhdp, + u32 pclock) +{ + struct imx_hdp_clks *clks = &imx_mhdp->clks; + + clk_set_rate(clks->clk_pxl, pclock); +} + +int cdns_mhdp_power_on_ls1028a(struct cdns_mhdp_device *mhdp) +{ + struct imx_mhdp_device *imx_mhdp = container_of + (mhdp, struct imx_mhdp_device, mhdp); + + /* clock init and rate set */ + ls1028a_clocks_init(imx_mhdp); + + ls1028a_pixel_clk_enable(imx_mhdp); + + /* Init pixel clock with 148.5MHz before FW init */ + ls1028a_pixel_clk_set_rate(imx_mhdp, 148500000); + + ls1028a_phy_reset(1); + + return 0; +} + +void cdns_mhdp_pclk_rate_ls1028a(struct cdns_mhdp_device *mhdp) +{ + struct imx_mhdp_device *imx_mhdp = container_of + (mhdp, struct imx_mhdp_device, mhdp); + + /* set pixel clock before video mode setup */ + ls1028a_pixel_clk_disable(imx_mhdp); + + ls1028a_pixel_clk_set_rate(imx_mhdp, imx_mhdp->mhdp.mode.clock * 1000); + + ls1028a_pixel_clk_enable(imx_mhdp); +} --- a/drivers/gpu/drm/imx/cdns-mhdp-imx.h +++ b/drivers/gpu/drm/imx/cdns-mhdp-imx.h @@ -78,4 +78,6 @@ void cdns_mhdp_plat_deinit_imx8qm(struct void cdns_mhdp_pclk_rate_imx8qm(struct cdns_mhdp_device *mhdp); int cdns_mhdp_firmware_init_imx8qm(struct cdns_mhdp_device *mhdp); int cdns_mhdp_power_on_imx8qm(struct cdns_mhdp_device *mhdp); +int cdns_mhdp_power_on_ls1028a(struct cdns_mhdp_device *mhdp); +void cdns_mhdp_pclk_rate_ls1028a(struct cdns_mhdp_device *mhdp); #endif /* CDNS_MHDP_IMX_H_ */