From 33c773eb62eaa1b4be3598eb91e7cd01b4ab4053 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 3 Sep 2020 10:01:22 +0200 Subject: [PATCH] drm/vc4: hdmi: Introduce resource init and variant The HDMI controllers found in the BCM2711 has a pretty different clock and registers areas than found in the older BCM283x SoCs. Let's create a variant structure to store the various adjustments we'll need later on, and a function to get the resources needed for one particular version. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/71cfa3ce3d865bbab52a0e5651bc052dc4893f11.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 75 ++++++++++++++++++++++------------ drivers/gpu/drm/vc4/vc4_hdmi.h | 10 +++++ 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 5c5684f91b69..c40050b908b5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1178,11 +1178,51 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = { }; #endif +static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) +{ + struct platform_device *pdev = vc4_hdmi->pdev; + struct device *dev = &pdev->dev; + int ret; + + vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); + if (IS_ERR(vc4_hdmi->hdmicore_regs)) + return PTR_ERR(vc4_hdmi->hdmicore_regs); + + vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); + if (IS_ERR(vc4_hdmi->hd_regs)) + return PTR_ERR(vc4_hdmi->hd_regs); + + vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs; + vc4_hdmi->hdmi_regset.regs = hdmi_regs; + vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs); + + vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs; + vc4_hdmi->hd_regset.regs = hd_regs; + vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs); + + vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); + if (IS_ERR(vc4_hdmi->pixel_clock)) { + ret = PTR_ERR(vc4_hdmi->pixel_clock); + if (ret != -EPROBE_DEFER) + DRM_ERROR("Failed to get pixel clock\n"); + return ret; + } + + vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); + if (IS_ERR(vc4_hdmi->hsm_clock)) { + DRM_ERROR("Failed to get HDMI state machine clock\n"); + return PTR_ERR(vc4_hdmi->hsm_clock); + } + + return 0; +} + static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) { #ifdef CONFIG_DRM_VC4_HDMI_CEC struct cec_connector_info conn_info; #endif + const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct vc4_hdmi *vc4_hdmi; @@ -1199,34 +1239,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) encoder = &vc4_hdmi->encoder.base.base; vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; vc4_hdmi->pdev = pdev; + vc4_hdmi->variant = variant; - vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); - if (IS_ERR(vc4_hdmi->hdmicore_regs)) - return PTR_ERR(vc4_hdmi->hdmicore_regs); - - vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); - if (IS_ERR(vc4_hdmi->hd_regs)) - return PTR_ERR(vc4_hdmi->hd_regs); - - vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs; - vc4_hdmi->hdmi_regset.regs = hdmi_regs; - vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs); - vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs; - vc4_hdmi->hd_regset.regs = hd_regs; - vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs); - - vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); - if (IS_ERR(vc4_hdmi->pixel_clock)) { - ret = PTR_ERR(vc4_hdmi->pixel_clock); - if (ret != -EPROBE_DEFER) - DRM_ERROR("Failed to get pixel clock\n"); + ret = variant->init_resources(vc4_hdmi); + if (ret) return ret; - } - vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); - if (IS_ERR(vc4_hdmi->hsm_clock)) { - DRM_ERROR("Failed to get HDMI state machine clock\n"); - return PTR_ERR(vc4_hdmi->hsm_clock); - } ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); if (!ddc_node) { @@ -1403,8 +1420,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) return 0; } +static const struct vc4_hdmi_variant bcm2835_variant = { + .init_resources = vc4_hdmi_init_resources, +}; + static const struct of_device_id vc4_hdmi_dt_match[] = { - { .compatible = "brcm,bcm2835-hdmi" }, + { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant }, {} }; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 674541493909..0eaf979fe811 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_hdmi_encoder, base.base); } +struct vc4_hdmi; + +struct vc4_hdmi_variant { + /* Callback to get the resources (memory region, interrupts, + * clocks, etc) for that variant. + */ + int (*init_resources)(struct vc4_hdmi *vc4_hdmi); +}; + /* HDMI audio information */ struct vc4_hdmi_audio { struct snd_soc_card card; @@ -39,6 +48,7 @@ struct vc4_hdmi { struct vc4_hdmi_audio audio; struct platform_device *pdev; + const struct vc4_hdmi_variant *variant; struct vc4_hdmi_encoder encoder; struct drm_connector connector;