From patchwork Tue Jul 23 18:34:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sui Jingfeng X-Patchwork-Id: 13740294 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 16A95C3DA63 for ; Tue, 23 Jul 2024 18:35:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5481F89A77; Tue, 23 Jul 2024 18:35:21 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=linux.dev header.i=@linux.dev header.b="nDNAJrf8"; dkim-atps=neutral Received: from out-172.mta1.migadu.com (out-172.mta1.migadu.com [95.215.58.172]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0475D10E620 for ; Tue, 23 Jul 2024 18:35:05 +0000 (UTC) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1721759703; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ILe9B/9Mphu0o7nKQGRaAxF7ht3JAsgY6SSklUtvM5Q=; b=nDNAJrf8Jj1ZHD/xnXW3tIBzYP/cKBmHUg9JNCpFeqL7QZB+UHvS6wx+VqPmDF+/np29Ay njQeqaP3E3G+BMNBFILnx3GGv1wNj3l/fRXJuX/ZofbKexE+XUOdUPP9xu/RsH8AySNd1o 1TR3hdKFkYxKGP3zazy9pWyQ7REj8Tg= From: Sui Jingfeng To: Markus Elfring , Maxime Ripard , Thomas Zimmermann Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Sui Jingfeng Subject: [PATCH v4 1/1] drm/loongson: Introduce component framework support Date: Wed, 24 Jul 2024 02:34:36 +0800 Message-ID: <20240723183436.216670-2-sui.jingfeng@linux.dev> In-Reply-To: <20240723183436.216670-1-sui.jingfeng@linux.dev> References: <20240723183436.216670-1-sui.jingfeng@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" In some display subsystems, the functionality of a PCIe device may too complex to be managed by a single driver. A split of the functionality into child devices can help to achieve better modularity. For example, KMS drivers who have dependencies on external modules will suffer from the deferral probe problem. The problem is that the DRM driver has to tear down everything when it receives '-EPROBE_DEFER', even though the independent part of the driver is not related to this error. Loongson Graphics are PCIe multifunctional devices, the GPU and the display controller are two distinct devices. Despite all hardware units that come along with PCIe are actually ready to be driven by the time of the dirver is loaded, drm/loongson driver still need to wait all of its dependencies ready before it can register the service to userspace. The idea is to migrate (offload) the dependency to submodules, creating submodule by creating platform devices manually during driverload time. Submodules are functional as agents, which will be responsible for attaching needed external modules for the main body of the whole KMS driver. Submodules are also responsible for returning '-EPROBE_DEFER' to the driver core if it needs to do so. Add a dummy GPU driver as a subcomponent, make LSDC PCI driver as a subcomponent as well. Introduce the component framework to bind those scatter software and/or hardware entities into one. Creating a platform device as a DRM proxy, which will attach the common drm routines to our hardware after all submodules bound. The proxy is the explicit executant working at the foreground, while the LSDC PCIe device is the master. Move DRM-related codes into the loongson_drm_master_bind(), move output related things into the submodule, because the output hardware units are relatively standalone IPs and the encoder/connector/transcoder may depend on external modules. While the display controller itself and GPIO-I2Cs have no dependency on external modules, therefore go with the LSDC PCIe device. Also assign GFX PLL, TTM memory manager part, and power management part to loongson drm proxy, as they do not belong to the LSDC itself. While at it, also do some cleanups. Signed-off-by: Sui Jingfeng --- drivers/gpu/drm/loongson/Makefile | 6 + drivers/gpu/drm/loongson/loonggpu_pci_drv.c | 163 ++++++++ drivers/gpu/drm/loongson/loonggpu_pci_drv.h | 35 ++ drivers/gpu/drm/loongson/loongson_device.c | 30 ++ drivers/gpu/drm/loongson/loongson_drv.c | 293 +++++++++++++ drivers/gpu/drm/loongson/loongson_drv.h | 90 ++++ drivers/gpu/drm/loongson/loongson_module.c | 84 +++- drivers/gpu/drm/loongson/loongson_module.h | 32 ++ drivers/gpu/drm/loongson/lsdc_benchmark.c | 12 +- drivers/gpu/drm/loongson/lsdc_benchmark.h | 2 +- drivers/gpu/drm/loongson/lsdc_component.c | 159 +++++++ drivers/gpu/drm/loongson/lsdc_crtc.c | 4 +- drivers/gpu/drm/loongson/lsdc_debugfs.c | 44 +- drivers/gpu/drm/loongson/lsdc_drv.c | 394 ++---------------- drivers/gpu/drm/loongson/lsdc_drv.h | 83 +--- drivers/gpu/drm/loongson/lsdc_gem.c | 44 +- drivers/gpu/drm/loongson/lsdc_gem.h | 19 +- drivers/gpu/drm/loongson/lsdc_gfxpll.c | 29 +- drivers/gpu/drm/loongson/lsdc_gfxpll.h | 3 +- drivers/gpu/drm/loongson/lsdc_i2c.c | 43 +- drivers/gpu/drm/loongson/lsdc_i2c.h | 12 +- drivers/gpu/drm/loongson/lsdc_output.c | 183 ++++++++ drivers/gpu/drm/loongson/lsdc_output.h | 36 +- drivers/gpu/drm/loongson/lsdc_output_7a1000.c | 14 +- drivers/gpu/drm/loongson/lsdc_output_7a2000.c | 20 +- drivers/gpu/drm/loongson/lsdc_plane.c | 4 +- drivers/gpu/drm/loongson/lsdc_ttm.c | 84 ++-- drivers/gpu/drm/loongson/lsdc_ttm.h | 4 +- 28 files changed, 1318 insertions(+), 608 deletions(-) create mode 100644 drivers/gpu/drm/loongson/loonggpu_pci_drv.c create mode 100644 drivers/gpu/drm/loongson/loonggpu_pci_drv.h create mode 100644 drivers/gpu/drm/loongson/loongson_drv.c create mode 100644 drivers/gpu/drm/loongson/loongson_drv.h create mode 100644 drivers/gpu/drm/loongson/lsdc_component.c create mode 100644 drivers/gpu/drm/loongson/lsdc_output.c diff --git a/drivers/gpu/drm/loongson/Makefile b/drivers/gpu/drm/loongson/Makefile index 91e72bd900c1..1c496713baa9 100644 --- a/drivers/gpu/drm/loongson/Makefile +++ b/drivers/gpu/drm/loongson/Makefile @@ -2,6 +2,7 @@ loongson-y := \ lsdc_benchmark.o \ + lsdc_component.o \ lsdc_crtc.o \ lsdc_debugfs.o \ lsdc_drv.o \ @@ -9,6 +10,7 @@ loongson-y := \ lsdc_gfxpll.o \ lsdc_i2c.o \ lsdc_irq.o \ + lsdc_output.o \ lsdc_output_7a1000.o \ lsdc_output_7a2000.o \ lsdc_plane.o \ @@ -16,7 +18,11 @@ loongson-y := \ lsdc_probe.o \ lsdc_ttm.o +loongson-y += \ + loonggpu_pci_drv.o + loongson-y += loongson_device.o \ + loongson_drv.o \ loongson_module.o obj-$(CONFIG_DRM_LOONGSON) += loongson.o diff --git a/drivers/gpu/drm/loongson/loonggpu_pci_drv.c b/drivers/gpu/drm/loongson/loonggpu_pci_drv.c new file mode 100644 index 000000000000..44c5fd93a69a --- /dev/null +++ b/drivers/gpu/drm/loongson/loonggpu_pci_drv.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Authors: + * Sui Jingfeng + */ + +#include +#include + +#include +#include + +#include "loongson_drv.h" +#include "loongson_module.h" +#include "loonggpu_pci_drv.h" + +static int loonggpu_get_version(struct loonggpu_device *gpu) +{ + u32 hw_info = loong_rreg32(gpu, 0x8C); + u8 host_id; + u8 revision; + + /* LoongGPU hardware info */ + gpu->ver_major = (hw_info >> 8) & 0x0F; + gpu->ver_minor = (hw_info & 0xF0) >> 4; + revision = hw_info & 0x0F; + host_id = (hw_info >> 16) & 0xFF; + + drm_info(gpu->drm, "LoongGPU(TM): LG%x%x0, revision: %x, Host: %s\n", + gpu->ver_major, gpu->ver_minor, revision, + host_id ? "LS2K2000" : "LS7A2000"); + + return 0; +} + +static irqreturn_t loonggpu_irq_handler(int irq, void *arg) +{ + struct loonggpu_device *gpu = arg; + + drm_dbg(gpu->drm, "LoongGPU interrupted\n"); + + return IRQ_HANDLED; +} + +static int loonggpu_component_bind(struct device *dev, + struct device *master, + void *data) +{ + struct loonggpu_device *gpu = dev_get_drvdata(dev); + struct drm_device *drm = data; + struct loongson_drm *ldrm = to_loongson_drm(drm); + struct pci_dev *pdev = to_pci_dev(dev); + int ret; + + gpu->drm = drm; + ldrm->loonggpu = gpu; + + loonggpu_get_version(gpu); + + ret = devm_request_irq(dev, + pdev->irq, + loonggpu_irq_handler, + IRQF_SHARED, + dev_name(dev), + gpu); + if (ret) + return ret; + + drm_info(gpu->drm, "LoongGPU irq: %d\n", pdev->irq); + + return 0; +} + +static void loonggpu_component_unbind(struct device *dev, + struct device *master, + void *data) +{ + dev_dbg(dev, "LoongGPU unbind\n"); +} + +static const struct component_ops loonggpu_component_ops = { + .bind = loonggpu_component_bind, + .unbind = loonggpu_component_unbind, +}; + +static int loonggpu_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct loonggpu_device *gpu; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + + gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL); + if (!gpu) + return -ENOMEM; + + gpu->pdev = pdev; + + gpu->reg_base = pcim_iomap(pdev, 0, 0); + if (!gpu->reg_base) + return -ENOMEM; + + pci_set_drvdata(pdev, gpu); + + dev_info(&pdev->dev, "LoongGPU(TM) PCI driver probed\n"); + + return component_add(&pdev->dev, &loonggpu_component_ops); +} + +static void loonggpu_pci_remove(struct pci_dev *pdev) +{ + component_del(&pdev->dev, &loonggpu_component_ops); +} + +static int loonggpu_pm_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int loonggpu_pm_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (pcim_enable_device(pdev)) + return -EIO; + + return 0; +} + +static const struct dev_pm_ops loonggpu_pm_ops = { + .suspend = loonggpu_pm_suspend, + .resume = loonggpu_pm_resume, +}; + +static const struct pci_device_id loonggpu_pci_id_list[] = { + {PCI_VDEVICE(LOONGSON, 0x7a25), CHIP_LS7A2000}, + { }, +}; + +struct pci_driver loonggpu_pci_driver = { + .name = "loongson.loonggpu", + .id_table = loonggpu_pci_id_list, + .probe = loonggpu_pci_probe, + .remove = loonggpu_pci_remove, + .driver.pm = &loonggpu_pm_ops, +}; + +MODULE_DEVICE_TABLE(pci, loonggpu_pci_id_list); diff --git a/drivers/gpu/drm/loongson/loonggpu_pci_drv.h b/drivers/gpu/drm/loongson/loonggpu_pci_drv.h new file mode 100644 index 000000000000..1ba64ef12835 --- /dev/null +++ b/drivers/gpu/drm/loongson/loonggpu_pci_drv.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Authors: + * Sui Jingfeng + */ + +#ifndef __LOONGGPU_PCI_DRV_H__ +#define __LOONGGPU_PCI_DRV_H__ + +#include +#include + +struct loonggpu_device { + struct pci_dev *pdev; + struct drm_device *drm; + + void __iomem *reg_base; + int irq; + + u32 ver_major; + u32 ver_minor; + u32 revision; +}; + +static inline u32 loong_rreg32(struct loonggpu_device *ldev, u32 offset) +{ + return readl(ldev->reg_base + offset); +} + +static inline void loong_wreg32(struct loonggpu_device *ldev, u32 offset, u32 val) +{ + writel(val, ldev->reg_base + offset); +} + +#endif diff --git a/drivers/gpu/drm/loongson/loongson_device.c b/drivers/gpu/drm/loongson/loongson_device.c index 9986c8a2a255..364b4bdbf0c5 100644 --- a/drivers/gpu/drm/loongson/loongson_device.c +++ b/drivers/gpu/drm/loongson/loongson_device.c @@ -4,6 +4,7 @@ */ #include +#include #include "lsdc_drv.h" @@ -100,3 +101,32 @@ lsdc_device_probe(struct pci_dev *pdev, enum loongson_chip_id chip_id) { return __chip_id_desc_table[chip_id]; } + +static void loongson_device_postfini(void *data) +{ + struct platform_device *proxy = data; + + platform_device_unregister(proxy); +} + +int loongson_device_preinit(struct device *parent) +{ + struct platform_device *proxy; + int ret; + + proxy = platform_device_register_resndata(parent, + "loongson", + PLATFORM_DEVID_NONE, + NULL, 0, + NULL, 0); + if (IS_ERR(proxy)) { + dev_err(parent, "failed to register loongson proxy device\n"); + return PTR_ERR(proxy); + } + + ret = devm_add_action_or_reset(parent, loongson_device_postfini, proxy); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpu/drm/loongson/loongson_drv.c b/drivers/gpu/drm/loongson/loongson_drv.c new file mode 100644 index 000000000000..346a06e80f91 --- /dev/null +++ b/drivers/gpu/drm/loongson/loongson_drv.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Authors: + * Sui Jingfeng + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "loonggpu_pci_drv.h" +#include "loongson_drv.h" +#include "loongson_module.h" +#include "lsdc_drv.h" +#include "lsdc_gem.h" +#include "lsdc_output.h" +#include "lsdc_ttm.h" + +DEFINE_DRM_GEM_FOPS(loongson_gem_fops); + +static const struct drm_driver loongson_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_RENDER | DRIVER_GEM | + DRIVER_ATOMIC, + .fops = &loongson_gem_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, + .debugfs_init = loongson_debugfs_init, + .dumb_create = lsdc_dumb_create, + .dumb_map_offset = lsdc_dumb_map_offset, + .gem_prime_import_sg_table = lsdc_prime_import_sg_table, +}; + +/* + * The GPU and display controller in the LS7A1000/LS7A2000/LS2K2000 are + * separated PCIE devices. They are two devices, not one. Bar 2 of the GPU + * device contains the base address and size of the VRAM, both the GPU and + * the DC could access the on-board VRAM. + */ +static int loongson_drm_get_dedicated_vram(struct drm_device *drm) +{ + struct loongson_drm *ldrm = to_loongson_drm(drm); + struct pci_dev *pdev_gpu; + resource_size_t base, size; + + /* + * The GPU has 00:06.0 as its BDF, this is true at least for + * LS7A1000, LS7A2000 and LS2K2000. + */ + pdev_gpu = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(6, 0)); + if (!pdev_gpu) { + drm_err(drm, "No GPU device, then no VRAM\n"); + return -ENODEV; + } + + base = pci_resource_start(pdev_gpu, 2); + size = pci_resource_len(pdev_gpu, 2); + + pci_dev_put(pdev_gpu); + + ldrm->vram_base = base; + ldrm->vram_size = size; + + drm_info(drm, "Dedicated vram start: 0x%llx, size: %uMiB\n", + (u64)base, (u32)(size >> 20)); + + return (size > SZ_1M) ? 0 : -ENODEV; +} + +static int loongson_drm_master_bind(struct device *dev) +{ + struct loongson_drm *ldrm = dev_get_drvdata(dev); + struct drm_device *ddev = &ldrm->ddev; + int ret; + + loongson_drm_get_dedicated_vram(ddev); + + loongson_gfxpll_preinit(ddev); + + ret = drmm_mode_config_init(ddev); + if (ret) + return ret; + + ret = component_bind_all(dev, ddev); + if (ret) { + dev_err(dev, "master bind all failed: %d\n", ret); + return ret; + } + + drm_mode_config_reset(ddev); + + lsdc_gem_init(ddev); + + ret = lsdc_ttm_init(ddev); + if (ret) { + drm_err(ddev, "Memory manager init failed: %d\n", ret); + return ret; + } + + drmm_kms_helper_poll_init(ddev); + + ret = drm_dev_register(ddev, 0); + if (ret) + return ret; + + drm_fbdev_ttm_setup(ddev, 32); + + return 0; +} + +static void loongson_drm_master_unbind(struct device *dev) +{ + struct loongson_drm *ldrm = dev_get_drvdata(dev); + struct drm_device *ddev = &ldrm->ddev; + + drm_atomic_helper_shutdown(ddev); + + drm_dev_unregister(ddev); + + component_unbind_all(dev, ddev); +} + +static const struct component_master_ops loongson_drm_master_ops = { + .bind = loongson_drm_master_bind, + .unbind = loongson_drm_master_unbind, +}; + +static int loongson_drm_freeze(struct drm_device *ddev) +{ + struct loongson_drm *ldrm = to_loongson_drm(ddev); + struct lsdc_bo *lbo; + int ret; + + /* unpin all of buffers in the VRAM */ + mutex_lock(&ldrm->gem.mutex); + list_for_each_entry(lbo, &ldrm->gem.objects, list) { + struct ttm_buffer_object *tbo = &lbo->tbo; + struct ttm_resource *resource = tbo->resource; + unsigned int pin_count = tbo->pin_count; + + drm_dbg(ddev, "bo[%p], size: %zuKiB, type: %s, pin count: %u\n", + lbo, lsdc_bo_size(lbo) >> 10, + lsdc_mem_type_to_str(resource->mem_type), pin_count); + + if (!pin_count) + continue; + + if (resource->mem_type == TTM_PL_VRAM) { + ret = lsdc_bo_reserve(lbo); + if (unlikely(ret)) { + drm_err(ddev, "bo reserve failed: %d\n", ret); + continue; + } + + do { + lsdc_bo_unpin(lbo); + --pin_count; + } while (pin_count); + + lsdc_bo_unreserve(lbo); + } + } + mutex_unlock(&ldrm->gem.mutex); + + lsdc_bo_evict_vram(ddev); + + ret = drm_mode_config_helper_suspend(ddev); + if (unlikely(ret)) { + drm_err(ddev, "Freeze error: %d", ret); + return ret; + } + + return 0; +} + +static int loongson_drm_pm_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct loongson_drm *ldrm = platform_get_drvdata(pdev); + + return loongson_drm_freeze(&ldrm->ddev); +} + +static int loongson_drm_pm_resume(struct platform_device *pdev) +{ + struct loongson_drm *ldrm = platform_get_drvdata(pdev); + + return drm_mode_config_helper_resume(&ldrm->ddev); +} + +static void loongson_add_pci_match(struct device *master, + struct device_driver *driver, + struct component_match **matchptr) +{ + struct pci_driver *pdriver = to_pci_driver(driver); + const struct pci_device_id *id_table = pdriver->id_table; + unsigned int i = 0; + struct pci_dev *pdev; + + while (id_table[i].vendor == PCI_VENDOR_ID_LOONGSON) { + pdev = pci_get_device(PCI_VENDOR_ID_LOONGSON, + id_table[i].device, + NULL); + if (!pdev) { + ++i; + continue; + } + + component_match_add(master, matchptr, component_compare_dev, + &pdev->dev); + pci_dev_put(pdev); + return; + } +} + +static void loongson_add_platform_match(struct device *master, + struct device_driver *driver, + struct component_match **matchptr) +{ + struct device *dev = NULL; + + while ((dev = platform_find_device_by_driver(dev, driver))) { + component_match_add(master, matchptr, component_compare_dev, dev); + put_device(dev); + } +} + +static void loongson_matches_add(struct device *master, + struct component_match **pptr) +{ + const struct loongson_driver_info *ldi; + + ldi = loongson_get_driver_info_array(NULL); + while (ldi->driver) { + if (ldi->type == LOONGSON_DRIVER_TYPE_PCI) + loongson_add_pci_match(master, ldi->driver, pptr); + else if (ldi->type == LOONGSON_DRIVER_TYPE_PLATFORM) + loongson_add_platform_match(master, ldi->driver, pptr); + + ++ldi; + } +} + +static int loongson_drm_driver_probe(struct platform_device *pdev) +{ + struct lsdc_device *lsdc = dev_get_drvdata(pdev->dev.parent); + struct component_match *matches = NULL; + struct loongson_drm *ldrm; + + ldrm = devm_drm_dev_alloc(pdev->dev.parent, + &loongson_drm_driver, + struct loongson_drm, ddev); + if (IS_ERR(ldrm)) + return PTR_ERR(ldrm); + + ldrm->lsdc = lsdc; + ldrm->gfxinfo = to_loongson_gfx(lsdc->descp); + platform_set_drvdata(pdev, ldrm); + + loongson_matches_add(&pdev->dev, &matches); + + dev_info(&pdev->dev, "drm proxy probed\n"); + + return component_master_add_with_match(&pdev->dev, + &loongson_drm_master_ops, + matches); +} + +static void loongson_drm_driver_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &loongson_drm_master_ops); +} + +struct platform_driver loongson_drm_platform_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = loongson_drm_driver_probe, + .remove_new = loongson_drm_driver_remove, + .suspend = loongson_drm_pm_suspend, + .resume = loongson_drm_pm_resume, +}; diff --git a/drivers/gpu/drm/loongson/loongson_drv.h b/drivers/gpu/drm/loongson/loongson_drv.h new file mode 100644 index 000000000000..e8875af66e12 --- /dev/null +++ b/drivers/gpu/drm/loongson/loongson_drv.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Authors: + * Sui Jingfeng + */ + +#ifndef __LOONGSON_DRV_H__ +#define __LOONGSON_DRV_H__ + +#include +#include +#include + +#include "loongson_module.h" +#include "lsdc_gem.h" +#include "lsdc_gfxpll.h" + +struct loongson_drm { + struct drm_device ddev; + + struct device *dev; + + /* submodules */ + struct lsdc_device *lsdc; + struct loonggpu_device *loonggpu; + + const struct loongson_gfx_desc *gfxinfo; + + struct loongson_gfxpll gfxpll; + + /* memory manager */ + struct ttm_device bdev; + resource_size_t vram_base; + resource_size_t vram_size; + resource_size_t gtt_base; + resource_size_t gtt_size; + + struct loongson_gem gem; + + /* tracking pinned memory */ + size_t vram_pinned_size; + size_t gtt_pinned_size; +}; + +static inline struct loongson_drm * +to_loongson_drm(struct drm_device *drm) +{ + return container_of(drm, struct loongson_drm, ddev); +} + +static inline struct lsdc_device * +to_lsdc(struct drm_device *drm) +{ + return to_loongson_drm(drm)->lsdc; +} + +static inline struct loonggpu_device * +to_loongpu(struct drm_device *drm) +{ + return to_loongson_drm(drm)->loonggpu; +} + +static inline resource_size_t +loongson_drm_vram_base(struct drm_device *drm) +{ + return to_loongson_drm(drm)->vram_base; +} + +static inline resource_size_t +loongson_drm_vram_size(struct drm_device *drm) +{ + return to_loongson_drm(drm)->vram_size; +} + +static inline struct loongson_gem * +to_loongson_gem(struct drm_device *drm) +{ + return &(to_loongson_drm(drm)->gem); +} + +static inline struct loongson_drm * +tdev_to_ldrm(struct ttm_device *tdev) +{ + return container_of(tdev, struct loongson_drm, bdev); +} + +int loongson_device_preinit(struct device *parent); +void loongson_debugfs_init(struct drm_minor *minor); + +#endif diff --git a/drivers/gpu/drm/loongson/loongson_module.c b/drivers/gpu/drm/loongson/loongson_module.c index d2a51bd395f6..a152146f5553 100644 --- a/drivers/gpu/drm/loongson/loongson_module.c +++ b/drivers/gpu/drm/loongson/loongson_module.c @@ -4,6 +4,7 @@ */ #include +#include #include