From patchwork Mon Mar 3 23:27:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 3757791 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8A2C5BF13A for ; Mon, 3 Mar 2014 23:27:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5F6CC203B6 for ; Mon, 3 Mar 2014 23:27:22 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 23704203AF for ; Mon, 3 Mar 2014 23:27:21 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 69CCDFA6CF; Mon, 3 Mar 2014 15:27:19 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qc0-f169.google.com (mail-qc0-f169.google.com [209.85.216.169]) by gabe.freedesktop.org (Postfix) with ESMTP id EB4FAFA6CF for ; Mon, 3 Mar 2014 15:27:17 -0800 (PST) Received: by mail-qc0-f169.google.com with SMTP id i17so1671434qcy.0 for ; Mon, 03 Mar 2014 15:27:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=0EZVrWleZWjkcvMLH2Gdqtat4Gqg/fMXrxAvlkeV/qA=; b=PY33cZvad241bh6d1EgaDzOCWZd7UqU95rZ6gHlyMjj7YOhFO3AYMCmKxMemtT5TjU uqMTikrzLmd0ADErC9BRP6+D4dxmw69mO6KcL99i9VP6AO2eS2KYggdAspoLdPwg4Vsv 8nTfAJe15RTpDVI0y6NGTy9ykUxROiRmjqsjT0jfYUpstkiSPFkVfUFXWttZJGAxXylm 5KR9t7dajP02AAXVWmHH8ALS8VMtrm6b+46n1Gy5RClxGo83+CR+RPxiNIW9SRQabOOc ZCjru7tw7qPwPTkpovGEuhWRTUxf8j0uqr20raJ2sP3LTCZaL+Uc0E2GYndqmd9FLA6w LB0w== X-Received: by 10.140.47.20 with SMTP id l20mr1137085qga.9.1393889237564; Mon, 03 Mar 2014 15:27:17 -0800 (PST) Received: from localhost (pool-108-20-244-150.bstnma.east.verizon.net. [108.20.244.150]) by mx.google.com with ESMTPSA id y19sm43250209qae.20.2014.03.03.15.27.16 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 03 Mar 2014 15:27:16 -0800 (PST) From: Rob Clark To: Russell King Subject: [RFC] drm/msm: use componentised device support Date: Mon, 3 Mar 2014 18:27:08 -0500 Message-Id: <1393889228-2128-1-git-send-email-robdclark@gmail.com> X-Mailer: git-send-email 1.8.5.3 Cc: dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hey Russell, Here is a early/rough pass at conversion to componentized device support. I was hoping you could have a quick look at this to make sure I'm on the right track, since there were no non-DT examples for me to look at ;-) I still haven't gotten rid of the global hdmi_pdev and a3xx_pdev ptrs. I am not entirely sure how to find those subordinate device pointers again without DT/phandle stuff. I think I might need something like: struct device *component_find(struct device *dev, const char *name) { struct master *master; struct component *c; struct device *component = NULL; mutex_lock(&component_mutex); master = __master_find(dev, NULL); if (master) { list_for_each_entry(c, &master->components, master_node) { if (!strcmp(name, dev_name(c->dev))) { /* maybe take a ref to the device? */ component = c->dev; break; } } } mutex_unlock(&component_mutex); return component; } or I could probably hack around it somehow in msm.. I suppose I'm the only one who still has to care for a bit longer about componentized + !DT. Also still need to remove the extra MODULE_DEVICE_TABLE()'s for DT case and few other little things. --- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 34 ++++++--- drivers/gpu/drm/msm/hdmi/hdmi.c | 38 +++++++--- drivers/gpu/drm/msm/msm_drv.c | 128 +++++++++++++++++++++++++++++++++- drivers/gpu/drm/msm/msm_drv.h | 1 + 4 files changed, 179 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index e6cb2bc..1f0bbf7 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -556,17 +556,17 @@ fail: # include #endif -static int a3xx_probe(struct platform_device *pdev) +static int a3xx_bind(struct device *dev, struct device *master, void *data) { static struct adreno_platform_config config = {}; #ifdef CONFIG_OF - struct device_node *child, *node = pdev->dev.of_node; + struct device_node *child, *node = dev->of_node; u32 val; int ret; ret = of_property_read_u32(node, "qcom,chipid", &val); if (ret) { - dev_err(&pdev->dev, "could not find chipid: %d\n", ret); + dev_err(dev, "could not find chipid: %d\n", ret); return ret; } @@ -582,7 +582,7 @@ static int a3xx_probe(struct platform_device *pdev) for_each_child_of_node(child, pwrlvl) { ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); if (ret) { - dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret); + dev_err(dev, "could not find gpu-freq: %d\n", ret); return ret; } config.fast_rate = max(config.fast_rate, val); @@ -592,12 +592,12 @@ static int a3xx_probe(struct platform_device *pdev) } if (!config.fast_rate) { - dev_err(&pdev->dev, "could not find clk rates\n"); + dev_err(dev, "could not find clk rates\n"); return -ENXIO; } #else - struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; + struct kgsl_device_platform_data *pdata = dev->platform_data; uint32_t version = socinfo_get_version(); if (cpu_is_apq8064ab()) { config.fast_rate = 450000000; @@ -643,14 +643,30 @@ static int a3xx_probe(struct platform_device *pdev) config.bus_scale_table = pdata->bus_scale_table; # endif #endif - pdev->dev.platform_data = &config; - a3xx_pdev = pdev; + dev->platform_data = &config; + a3xx_pdev = to_platform_device(dev); return 0; } -static int a3xx_remove(struct platform_device *pdev) +static void a3xx_unbind(struct device *dev, struct device *master, + void *data) { a3xx_pdev = NULL; +} + +static const struct component_ops a3xx_ops = { + .bind = a3xx_bind, + .unbind = a3xx_unbind, +}; + +static int a3xx_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &a3xx_ops); +} + +static int a3xx_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &a3xx_ops); return 0; } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index b8d902d..71c58b9 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -255,17 +255,17 @@ fail: #include -static int hdmi_dev_probe(struct platform_device *pdev) +static int hdmi_bind(struct device *dev, struct device *master, void *data) { static struct hdmi_platform_config config = {}; #ifdef CONFIG_OF - struct device_node *of_node = pdev->dev.of_node; + struct device_node *of_node = dev->of_node; int get_gpio(const char *name) { int gpio = of_get_named_gpio(of_node, name, 0); if (gpio < 0) { - dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n", + dev_err(dev, "failed to get gpio: %s (%d)\n", name, gpio); gpio = -1; } @@ -342,8 +342,30 @@ static int hdmi_dev_probe(struct platform_device *pdev) config.mux_sel_gpio = -1; } #endif - pdev->dev.platform_data = &config; - hdmi_pdev = pdev; + dev->platform_data = &config; + hdmi_pdev = to_platform_device(dev); + return 0; +} + +static void hdmi_unbind(struct device *dev, struct device *master, + void *data) +{ + hdmi_pdev = NULL; +} + +static const struct component_ops hdmi_ops = { + .bind = hdmi_bind, + .unbind = hdmi_unbind, +}; + +static int hdmi_dev_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &hdmi_ops); +} + +static int hdmi_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &hdmi_ops); return 0; } @@ -361,12 +383,6 @@ void hdmi_msm_audio_sample_rate_reset(int rate) } EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset); -static int hdmi_dev_remove(struct platform_device *pdev) -{ - hdmi_pdev = NULL; - return 0; -} - static const struct of_device_id dt_match[] = { { .compatible = "qcom,hdmi-tx" }, {} diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index e913efa..0b38be0 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -56,6 +56,10 @@ static char *vram; MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); module_param(vram, charp, 0); +/* + * Util/helpers: + */ + void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, const char *dbgname) { @@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev) priv->vram.paddr, &attrs); } + component_unbind_all(dev->dev, dev); + dev->dev_private = NULL; kfree(priv); @@ -175,6 +181,11 @@ static int msm_load(struct drm_device *dev, unsigned long flags) struct msm_kms *kms; int ret; + /* Bind all our sub-components: */ + ret = component_bind_all(dev->dev, dev); + if (ret) + return ret; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(dev->dev, "failed to allocate private data\n"); @@ -824,18 +835,131 @@ static const struct dev_pm_ops msm_pm_ops = { }; /* + * Componentized driver support: + */ + +#ifdef CONFIG_OF +/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx + * (or probably any other).. so probably some room for some helpers + */ +static int compare_parent_of(struct device *dev, void *data) +{ + struct of_phandle_args *args = data; + return dev->parent && dev->parent->of_node == args->np; +} + +static int compare_of(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +static int msm_drm_add_components(struct device *master, struct master *m) +{ + struct device_node *np = master->of_node; + unsigned i; + int ret; + + for (i = 0; ; i++) { + struct of_phandle_args args; + + ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1, + i, &args); + if (ret) + break; + + ret = component_master_add_child(m, compare_parent_of, &args); + of_node_put(args.np); + + if (ret) + return ret; + } + + for (i = 0; ; i++) { + struct device_node *node; + + node = of_parse_phandle(np, "connectors", i); + if (!node) + break; + + ret = component_master_add_child(m, compare_of, node); + of_node_put(node); + + if (ret) + return ret; + } + return 0; +} +#else +static int compare_dev(struct device *dev, void *data) +{ + return dev == data; +} + +static int msm_drm_add_components(struct device *master, struct master *m) +{ + /* For non-DT case, it kinda sucks. We don't actually have a way + * to know whether or not we are waiting for certain devices (or if + * they are simply not present). But for non-DT we only need to + * care about apq8064/apq8060/etc (all mdp4/a3xx): + */ + static const char *devnames[] = { + "hdmi_msm.0", "kgsl-3d0.0", + }; + int i; + + DBG("Adding components.."); + + for (i = 0; i < ARRAY_SIZE(devnames); i++) { + struct device *dev; + int ret; + + dev = bus_find_device_by_name(&platform_bus_type, + NULL, devnames[i]); + if (!dev) { + dev_info(master, "still waiting for %s\n", devnames[i]); + return -EPROBE_DEFER; + } + + ret = component_master_add_child(m, compare_dev, dev); + if (ret) { + DBG("could not add child: %d", ret); + return ret; + } + } + + return 0; +} +#endif + +static int msm_drm_bind(struct device *dev) +{ + return drm_platform_init(&msm_driver, to_platform_device(dev)); +} + +static void msm_drm_unbind(struct device *dev) +{ + drm_put_dev(platform_get_drvdata(to_platform_device(dev))); +} + +static const struct component_master_ops msm_drm_ops = { + .add_components = msm_drm_add_components, + .bind = msm_drm_bind, + .unbind = msm_drm_unbind, +}; + +/* * Platform driver: */ static int msm_pdev_probe(struct platform_device *pdev) { pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - return drm_platform_init(&msm_driver, pdev); + return component_master_add(&pdev->dev, &msm_drm_ops); } static int msm_pdev_remove(struct platform_device *pdev) { - drm_put_dev(platform_get_drvdata(pdev)); + component_master_del(&pdev->dev, &msm_drm_ops); return 0; } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 3d63269..d26bbdc 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include