[Openpvrsgx-devgroup] [PATCH] staging: pvr: Add a simplified pvr-drv.c as replacement for messy pvr_drm.c
H. Nikolaus Schaller
hns at goldelico.com
Thu Nov 7 08:43:31 CET 2019
Hi Tony,
cool work!
I'll try asap and then comment.
BR and thanks,
Nikolaus
> Am 07.11.2019 um 02:35 schrieb Tony Lindgren <tony at atomide.com>:
>
> We can have just a basic Linux DRM driver that uses the functions from the
> Imagination DDK. This makes it easier to rewrite components from the
> Imagination DDK rather than spend time on cleaning up the existing stuff.
>
> I've added basic quirk support based on the compatible, but that is not
> yet used. It can be used to set flags to init let's say pvr-sgx530.c
> and pvr-sgx540.c for the different register defines.
>
> Eventually this driver could become a standalone driver with integrated 2D
> acceleration capabilities along the lines we already have in the gma500
> driver in drivers/gpu/drm/gma500/accel_2d.c.
>
> At some point we should probably move most of the Makefile logic to the
> top level Makefile, but that can wait.
>
> Signed-off-by: Tony Lindgren <tony at atomide.com>
> ---
>
> Please test with the demos too.
>
> I've only tested pvrsrvctl --start --no-module on beagle-x15 to make sure
> things still load
>
> ---
> .../pvr/1.14.3699939/eurasia_km/Makefile | 11 +-
> drivers/staging/pvr/pvr-drv.c | 330 ++++++++++++++++++
> drivers/staging/pvr/pvr-drv.h | 126 +++++++
> 3 files changed, 465 insertions(+), 2 deletions(-)
> create mode 100644 drivers/staging/pvr/pvr-drv.c
> create mode 100644 drivers/staging/pvr/pvr-drv.h
>
> diff --git a/drivers/staging/pvr/1.14.3699939/eurasia_km/Makefile b/drivers/staging/pvr/1.14.3699939/eurasia_km/Makefile
> --- a/drivers/staging/pvr/1.14.3699939/eurasia_km/Makefile
> +++ b/drivers/staging/pvr/1.14.3699939/eurasia_km/Makefile
> @@ -34,6 +34,9 @@ ccflags-y += -DPVR_BUILD_DATE="\"$(shell date "+%Y%m%d" )\""
> # this defines the compatible string which must be present in the DTB of the board
> ccflags-y += -DSYS_SGX_DEV_NAME="\"$(SOC_VENDOR),$(SOC)-$(SGX)-$(SGX_REV)\""
>
> +# vendor_soc_sgx_rev for macro use
> +ccflags-y += -D$(SOC_VENDOR)_$(SOC)_$(SGX)_$(SGX_REV)
> +
> ccflags-y += -DSGX_CORE_REV=$(SGX_REV)
>
> ccflags-y += \
> @@ -149,6 +152,11 @@ ccflags-y += \
> -fno-strict-aliasing -Wno-pointer-arith -Wno-sign-conversion
> endif
>
> +# Add rewritten driver components here for now
> +$(TARGET) += \
> + ../../pvr-drv.o \
> +
> +# Keep Imagination SDK components here
> $(TARGET) += \
> services4/srvkm/bridged/bridged_pvr_bridge.o \
> services4/srvkm/bridged/bridged_support.o \
> @@ -190,8 +198,7 @@ $(TARGET) += \
> services4/srvkm/env/linux/pdump.o \
> services4/srvkm/env/linux/proc.o \
> services4/srvkm/env/linux/pvr_bridge_k.o \
> - services4/srvkm/env/linux/pvr_debug.o \
> - services4/srvkm/env/linux/pvr_drm.o
> + services4/srvkm/env/linux/pvr_debug.o
>
> ifneq ($(CONFIG_SGX_DRM),)
>
> diff --git a/drivers/staging/pvr/pvr-drv.c b/drivers/staging/pvr/pvr-drv.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/staging/pvr/pvr-drv.c
> @@ -0,0 +1,330 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Linux DRM Driver for PoverVR SGX
> + *
> + * Copyright (C) 2019 Tony Lindgren <tony at atomide.com>
> + *
> + * Some parts of code based on earlier Imagination driver
> + * Copyright (C) Imagination Technologies Ltd.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm.h>
> +#include <drm/drm_modeset_helper.h>
> +
> +#include "pvr-drv.h"
> +
> +/* Currently used Imagination SDK includes */
> +#include "services.h"
> +#include "mmap.h"
> +#include "linkage.h"
> +#include "pvr_bridge.h"
> +#include "pvrversion.h"
> +
> +#define PVR_DRM_NAME PVRSRV_MODNAME
> +#define PVR_DRM_DESC "Imagination Technologies PVR DRM"
> +#define PVR_DRM_DATE "20110701"
> +
> +#define PVR_QUIRK_OMAP4 BIT(0)
> +
> +struct pvr_capabilities {
> + u32 quirks;
> + unsigned long smp:1;
> +};
> +
> +struct pvr {
> + struct device *dev;
> + struct drm_device *ddev;
> + const struct pvr_capabilities *cap;
> + u32 quirks;
> +};
> +
> +struct platform_device *gpsPVRLDMDev;
> +static struct drm_device *gpsPVRDRMDev;
> +
> +static int pvr_drm_load(struct drm_device *dev, unsigned long flags)
> +{
> + dev_dbg(dev->dev, "%s\n", __func__);
> + gpsPVRDRMDev = dev;
> + gpsPVRLDMDev = to_platform_device(dev->dev);
> +
> + return PVRCore_Init();
> +}
> +
> +static int pvr_drm_unload(struct drm_device *dev)
> +{
> + dev_dbg(dev->dev, "%s\n", __func__);
> + PVRCore_Cleanup();
> +
> + return 0;
> +}
> +
> +static int pvr_open(struct drm_device *dev, struct drm_file *file)
> +{
> + dev_dbg(dev->dev, "%s\n", __func__);
> +
> + return PVRSRVOpen(dev, file);
> +}
> +
> +static int pvr_ioctl_command(struct drm_device *dev, void *arg, struct drm_file *filp)
> +{
> + dev_dbg(dev->dev, "%s: dev: %px arg: %px filp: %px\n", __func__, dev, arg, filp);
> +
> + return PVRSRV_BridgeDispatchKM(dev, arg, filp);
> +}
> +
> +static int pvr_ioctl_drm_is_master(struct drm_device *dev, void *arg, struct drm_file *filp)
> +{
> + dev_dbg(dev->dev, "%s: dev: %px arg: %px filp: %px\n", __func__, dev, arg, filp);
> +
> + return 0;
> +}
> +
> +static int pvr_ioctl_unpriv(struct drm_device *dev, void *arg, struct drm_file *filp)
> +{
> + dev_dbg(dev->dev, "%s: dev: %px arg: %px filp: %px\n", __func__, dev, arg, filp);
> +
> + return 0;
> +}
> +
> +static int pvr_ioctl_dbgdrv(struct drm_device *dev, void *arg, struct drm_file *filp)
> +{
> + dev_dbg(dev->dev, "%s: dev: %px arg: %px filp: %px\n", __func__, dev, arg, filp);
> +
> +#ifdef PDUMP
> + return dbgdrv_ioctl(dev, arg, filp);
> +#endif
> +
> + return 0;
> +}
> +
> +static struct drm_ioctl_desc pvr_ioctls[] = {
> + DRM_IOCTL_DEF_DRV(PVR_SRVKM, pvr_ioctl_command, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(PVR_IS_MASTER, pvr_ioctl_drm_is_master,
> + DRM_RENDER_ALLOW | DRM_MASTER),
> + DRM_IOCTL_DEF_DRV(PVR_UNPRIV, pvr_ioctl_unpriv, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(PVR_DBGDRV, pvr_ioctl_dbgdrv, DRM_RENDER_ALLOW),
> +#ifdef PVR_DISPLAY_CONTROLLER_DRM_IOCTL
> + DRM_IOCTL_DEF_DRV(PVR_DISP, drm_invalid_op, DRM_MASTER)
> +#endif
> +};
> +
> +/* REVISIT: This is used by dmabuf.c */
> +struct device *PVRLDMGetDevice(void)
> +{
> + return gpsPVRDRMDev->dev;
> +}
> +
> +static const struct file_operations pvr_fops = {
> + .owner = THIS_MODULE,
> + .open = drm_open,
> + .unlocked_ioctl = drm_ioctl,
> + .compat_ioctl = drm_compat_ioctl,
> + .mmap = PVRMMap,
> + .poll = drm_poll,
> + .read = drm_read,
> + .llseek = noop_llseek,
> +};
> +
> +static struct drm_driver pvr_drm_driver = {
> + .driver_features = DRIVER_RENDER,
> + .dev_priv_size = 0,
> + .open = pvr_open,
> + .ioctls = pvr_ioctls,
> + .num_ioctls = ARRAY_SIZE(pvr_ioctls),
> + .fops = &pvr_fops,
> + .name = "pvr",
> + .desc = PVR_DRM_DESC,
> + .date = PVR_DRM_DATE,
> + .major = PVRVERSION_MAJ,
> + .minor = PVRVERSION_MIN,
> + .patchlevel = PVRVERSION_BUILD,
> +};
> +
> +static int __maybe_unused pvr_runtime_suspend(struct device *dev)
> +{
> + dev_dbg(dev, "%s\n", __func__);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused pvr_runtime_resume(struct device *dev)
> +{
> + dev_dbg(dev, "%s\n", __func__);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int pvr_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct pvr *ddata = dev_get_drvdata(dev);
> + struct drm_device *drm_dev = ddata->ddev;
> + int error;
> +
> + error = drm_mode_config_helper_suspend(drm_dev);
> + if (error)
> + dev_warn(dev, "%s: error: %i\n", __func__, error);
> +
> + return PVRSRVDriverSuspend(pdev, PMSG_SUSPEND);
> +}
> +
> +static int pvr_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct pvr *ddata = dev_get_drvdata(dev);
> + struct drm_device *drm_dev = ddata->ddev;
> + int error;
> +
> + error = drm_mode_config_helper_resume(drm_dev);
> + if (error)
> + dev_warn(dev, "%s: error: %i\n", __func__, error);
> +
> + return PVRSRVDriverResume(pdev);
> +}
> +#endif
> +
> +static const struct dev_pm_ops pvr_pm_ops = {
> + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pvr_suspend, pvr_resume)
> + SET_RUNTIME_PM_OPS(pvr_runtime_suspend,
> + pvr_runtime_resume,
> + NULL)
> +};
> +
> +static const struct pvr_capabilities __maybe_unused pvr_omap3 = {
> +};
> +
> +static const struct pvr_capabilities __maybe_unused pvr_omap4 = {
> + .quirks = PVR_QUIRK_OMAP4,
> +};
> +
> +static const struct pvr_capabilities __maybe_unused pvr_omap4470 = {
> + .smp = true,
> +};
> +
> +static const struct pvr_capabilities __maybe_unused pvr_omap5 = {
> + .smp = true,
> +};
> +
> +static const struct of_device_id pvr_ids[] = {
> + OMAP3_SGX530_121("ti,omap3-sgx530-121", &pvr_omap3)
> + OMAP3630_SGX530_125("ti,omap3-sgx530-125", &pvr_omap3)
> + AM3517_SGX530_125("ti,am3517-sgx530-125", &pvr_omap3)
> + AM335X_SGX530_125("ti,am335x-sgx530-125", &pvr_omap3)
> + OMAP4_SGX540_120("ti,omap4-sgx540-120", &pvr_omap4)
> + OMAP4470_SGX544_112("ti,omap4-sgx544-112", &pvr_omap4470)
> + OMAP5_SGX544_116("ti,omap5-sgx544-116", &pvr_omap5)
> + DRA7_SGX544_116("ti,dra7-sgx544-116", &pvr_omap5)
> + { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, pvr_ids);
> +
> +static int pvr_init_match(struct pvr *ddata)
> +{
> + const struct pvr_capabilities *cap;
> +
> + cap = of_device_get_match_data(ddata->dev);
> + if (!cap)
> + return 0;
> +
> + ddata->cap = cap;
> +
> + ddata->quirks = cap->quirks;
> + dev_info(ddata->dev, "Enabling quirks %08x\n", ddata->quirks);
> +
> + return 0;
> +}
> +
> +static int pvr_probe(struct platform_device *pdev)
> +{
> + struct drm_device *ddev;
> + struct pvr *ddata;
> + int error;
> +
> + ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
> + if (!ddata)
> + return -ENOMEM;
> +
> + ddata->dev = &pdev->dev;
> + platform_set_drvdata(pdev, ddata);
> +
> + error = pvr_init_match(ddata);
> + if (error)
> + return error;
> +
> + pm_runtime_enable(ddata->dev);
> + error = pm_runtime_get_sync(ddata->dev);
> + if (error < 0) {
> + pm_runtime_put_noidle(ddata->dev);
> +
> + return error;
> + }
> +
> + ddev = drm_dev_alloc(&pvr_drm_driver, ddata->dev);
> + if (IS_ERR(ddev))
> + return PTR_ERR(ddev);
> +
> + error = pvr_drm_load(ddev, 0);
> + if (error)
> + return error;
> +
> + error = drm_dev_register(ddev, 0);
> + if (error < 0) {
> + pvr_drm_unload(gpsPVRDRMDev);
> +
> + return error;
> + }
> +
> + ddata->ddev = ddev;
> + ddev->dev_private = ddata;
> +
> + gpsPVRLDMDev = pdev;
> +
> + return 0;
> +}
> +
> +static int pvr_remove(struct platform_device *pdev)
> +{
> + drm_put_dev(gpsPVRDRMDev);
> + pvr_drm_unload(gpsPVRDRMDev);
> + gpsPVRDRMDev = NULL;
> +
> + pm_runtime_put_sync(&pdev->dev);
> + pm_runtime_disable(&pdev->dev);
> +
> + return 0;
> +}
> +
> +static struct platform_driver pvr_driver = {
> + .driver = {
> + .name = PVR_DRM_NAME,
> + .of_match_table = pvr_ids,
> + .pm = &pvr_pm_ops,
> + },
> + .probe = pvr_probe,
> + .remove = pvr_remove,
> + .shutdown = PVRSRVDriverShutdown,
> +};
> +
> +static int __init pvr_init(void)
> +{
> + /* Must come before attempting to print anything via Services */
> + PVRDPFInit();
> +
> + return platform_driver_register(&pvr_driver);
> +}
> +
> +static void __exit pvr_exit(void)
> +{
> + platform_driver_unregister(&pvr_driver);
> +}
> +
> +module_init(pvr_init);
> +module_exit(pvr_exit);
> diff --git a/drivers/staging/pvr/pvr-drv.h b/drivers/staging/pvr/pvr-drv.h
> new file mode 100644
> --- /dev/null
> +++ b/drivers/staging/pvr/pvr-drv.h
> @@ -0,0 +1,126 @@
> +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
> +
> +struct pvr_ioctl {
> + u32 ui32Cmd; /* ioctl command */
> + u32 ui32Size; /* needs to be correctly set */
> + void *pInBuffer; /* input data buffer */
> + u32 ui32InBufferSize; /* size of input data buffer */
> + void *pOutBuffer; /* output data buffer */
> + u32 ui32OutBufferSize; /* size of output data buffer */
> +};
> +
> +struct pvr_dummy {
> + char dummy[4];
> +};
> +
> +struct pvr_unpriv {
> + u32 cmd;
> + u32 res;
> +};
> +
> +#define DRM_PVR_SRVKM 0x0
> +#define DRM_PVR_DISP 0x1
> +#define DRM_PVR_BC 0x2
> +#define DRM_PVR_IS_MASTER 0x3
> +#define DRM_PVR_UNPRIV 0x4
> +#define DRM_PVR_DBGDRV 0x5
> +
> +#define DRM_IOCTL_PVR_SRVKM DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_SRVKM, PVRSRV_BRIDGE_PACKAGE)
> +#define DRM_IOCTL_PVR_IS_MASTER DRM_IOW(DRM_COMMAND_BASE + DRM_PVR_IS_MASTER, struct pvr_dummy)
> +#define DRM_IOCTL_PVR_UNPRIV DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_UNPRIV, struct pvr_unpriv)
> +#define DRM_IOCTL_PVR_DBGDRV DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_DBGDRV, struct pvr_ioctl)
> +#define DRM_IOCTL_PVR_DISP DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_DISP, drm_pvr_display_cmd)
> +
> +/* We are currently calling these from the Imagination SDK */
> +int PVRCore_Init(void);
> +void PVRCore_Cleanup(void);
> +int PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
> +void PVRSRVRelease(void *pvPrivData);
> +int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile);
> +int PVRSRVDriverSuspend(struct platform_device *pdev, pm_message_t state);
> +int PVRSRVDriverResume(struct platform_device *pdev);
> +void PVRSRVDriverShutdown(struct platform_device *pdev);
> +
> +/*
> + * These are currently needed to prevent the multiple instances of
> + * the driver from trying to probe.
> + */
> +#ifdef ti_omap3_sgx530_121
> +#define OMAP3_SGX530_121(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define OMAP3_SGX530_121(comp, dat)
> +#endif
> +
> +#ifdef ti_omap3630_sgx530_125
> +#define OMAP3630_SGX530_125(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define OMAP3630_SGX530_125(comp, dat)
> +#endif
> +
> +#ifdef ti_am3517_sgx530_125
> +#define AM3517_SGX530_125(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define AM3517_SGX530_125(comp, dat)
> +#endif
> +
> +#ifdef ti_am335x_sgx530_125
> +#define AM335X_SGX530_125(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define AM335X_SGX530_125(comp, dat)
> +#endif
> +
> +#ifdef ti_omap4_sgx540_120
> +#define OMAP4_SGX540_120(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define OMAP4_SGX540_120(comp, dat)
> +#endif
> +
> +#ifdef ti_omap44370_sgx544_112
> +#define OMAP4470_SGX544_112(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define OMAP4470_SGX544_112(comp, dat)
> +#endif
> +
> +#ifdef ti_omap5_sgx544_116
> +#define OMAP5_SGX544_116(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define OMAP5_SGX544_116(comp, dat)
> +#endif
> +
> +#ifdef ti_dra7_sgx544_116
> +#define DRA7_SGX544_116(comp, dat) \
> + { \
> + .compatible = comp, \
> + .data = dat, \
> + },
> +#else
> +#define DRA7_SGX544_116(comp, dat)
> +#endif
> --
> 2.23.0
More information about the openpvrsgx-devgroup
mailing list