diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 18:48:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 18:48:37 -0700 |
commit | af3c8d98508d37541d4bf57f13a984a7f73a328c (patch) | |
tree | e8dd974d6ebccd38b1e373be8a5e4a2f8bf3c6ce /drivers/gpu/drm/pl111/pl111_drv.c | |
parent | d3e3b7eac886fb1383db2f22b81550fa6d87f62f (diff) | |
parent | 00fc2c26bc46a64545cdf95a1511461ea9acecb4 (diff) |
Merge tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main pull request for the drm, I think I've got one later
driver pull for mediatek SoC driver, I'm undecided on if it needs to
go to you yet.
Otherwise summary below:
Core drm:
- Atomic add driver private objects
- Deprecate preclose hook in modern drivers
- MST bandwidth tracking
- Use kvmalloc in more places
- Add mode_valid hook for crtc/encoder/bridge
- Reduce sync_file construction time
- Documentation updates
- New DRM synchronisation object support
New drivers:
- pl111 - pl111 CLCD display controller
Panel:
- Innolux P079ZCA panel driver
- Add NL12880B20-05, NL192108AC18-02D, P320HVN03 panels
- panel-samsung-s6e3ha2: Add s6e3hf2 panel support
i915:
- SKL+ watermark fixes
- G4x/G33 reset improvements
- DP AUX backlight improvements
- Buffer based GuC/host communication
- New getparam for (sub)slice infomation
- Cannonlake and Coffeelake initial patches
- Execbuf optimisations
radeon/amdgpu:
- Lots of Vega10 bug fixes
- Preliminary raven support
- KIQ support for compute rings
- MEC queue management rework
- DCE6 Audio support
- SR-IOV improvements
- Better radeon/amdgpu selection support
nouveau:
- HDMI stereoscopic support
- Display code rework for >= GM20x GPUs
msm:
- GEM rework for fine-grained locking
- Per-process pagetable work
- HDMI fixes for Snapdragon 820.
vc4:
- Remove 256MB CMA limit from vc4
- Add out-fence support
- Add support for cygnus
- Get/set tiling ioctls support
- Add T-format tiling support for scanout
zte:
- add VGA support.
etnaviv:
- Thermal throttle support for newer GPUs
- Restore userspace buffer cache performance
- dma-buf sync fix
stm:
- add stm32f429 display support
exynos:
- Rework vblank handling
- Fixup sw-trigger code
sun4i:
- V3s display engine support
- HDMI support for older SoCs
- Preliminary work on dual-pipeline SoCs.
rcar-du:
- VSP work
imx-drm:
- Remove counter load enable from PRE
- Double read/write reduction flag support
tegra:
- Documentation for the host1x and drm driver.
- Lots of staging ioctl fixes due to grate project work.
omapdrm:
- dma-buf fence support
- TILER rotation fixes"
* tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux: (1270 commits)
drm: Remove unused drm_file parameter to drm_syncobj_replace_fence()
drm/amd/powerplay: fix bug fail to remove sysfs when rmmod amdgpu.
amdgpu: Set cik/si_support to 1 by default if radeon isn't built
drm/amdgpu/gfx9: fix driver reload with KIQ
drm/amdgpu/gfx8: fix driver reload with KIQ
drm/amdgpu: Don't call amd_powerplay_destroy() if we don't have powerplay
drm/ttm: Fix use-after-free in ttm_bo_clean_mm
drm/amd/amdgpu: move get memory type function from early init to sw init
drm/amdgpu/cgs: always set reference clock in mode_info
drm/amdgpu: fix vblank_time when displays are off
drm/amd/powerplay: power value format change for Vega10
drm/amdgpu/gfx9: support the amdgpu.disable_cu option
drm/amd/powerplay: change PPSMC_MSG_GetCurrPkgPwr for Vega10
drm/amdgpu: Make amdgpu_cs_parser_init static (v2)
drm/amdgpu/cs: fix a typo in a comment
drm/amdgpu: Fix the exported always on CU bitmap
drm/amdgpu/gfx9: gfx_v9_0_enable_gfx_static_mg_power_gating() can be static
drm/amdgpu/psp: upper_32_bits/lower_32_bits for address setup
drm/amd/powerplay/cz: print message if smc message fails
drm/amdgpu: fix typo in amdgpu_debugfs_test_ib_init
...
Diffstat (limited to 'drivers/gpu/drm/pl111/pl111_drv.c')
-rw-r--r-- | drivers/gpu/drm/pl111/pl111_drv.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c new file mode 100644 index 000000000000..ac8771be70b0 --- /dev/null +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -0,0 +1,269 @@ +/* + * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. + * + * Parts of this file were based on sources as follows: + * + * Copyright (c) 2006-2008 Intel Corporation + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (C) 2011 Texas Instruments + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms of + * such GNU licence. + * + */ + +/** + * DOC: ARM PrimeCell PL111 CLCD Driver + * + * The PL111 is a simple LCD controller that can support TFT and STN + * displays. This driver exposes a standard KMS interface for them. + * + * This driver uses the same Device Tree binding as the fbdev CLCD + * driver. While the fbdev driver supports panels that may be + * connected to the CLCD internally to the CLCD driver, in DRM the + * panels get split out to drivers/gpu/drm/panels/. This means that, + * in converting from using fbdev to using DRM, you also need to write + * a panel driver (which may be as simple as an entry in + * panel-simple.c). + * + * The driver currently doesn't expose the cursor. The DRM API for + * cursors requires support for 64x64 ARGB8888 cursor images, while + * the hardware can only support 64x64 monochrome with masking + * cursors. While one could imagine trying to hack something together + * to look at the ARGB8888 and program reasonable in monochrome, we + * just don't expose the cursor at all instead, and leave cursor + * support to the X11 software cursor layer. + * + * TODO: + * + * - Fix race between setting plane base address and getting IRQ for + * vsync firing the pageflip completion. + * + * - Expose the correct set of formats we can support based on the + * "arm,pl11x,tft-r0g0b0-pads" DT property. + * + * - Use the "max-memory-bandwidth" DT property to filter the + * supported formats. + * + * - Read back hardware state at boot to skip reprogramming the + * hardware when doing a no-op modeset. + * + * - Use the CLKSEL bit to support switching between the two external + * clock parents. + */ + +#include <linux/amba/bus.h> +#include <linux/amba/clcd-regs.h> +#include <linux/version.h> +#include <linux/shmem_fs.h> +#include <linux/dma-buf.h> +#include <linux/module.h> +#include <linux/slab.h> + +#include <drm/drmP.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "pl111_drm.h" + +#define DRIVER_DESC "DRM module for PL111" + +static struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = drm_fb_cma_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int pl111_modeset_init(struct drm_device *dev) +{ + struct drm_mode_config *mode_config; + struct pl111_drm_dev_private *priv = dev->dev_private; + int ret = 0; + + drm_mode_config_init(dev); + mode_config = &dev->mode_config; + mode_config->funcs = &mode_config_funcs; + mode_config->min_width = 1; + mode_config->max_width = 1024; + mode_config->min_height = 1; + mode_config->max_height = 768; + + ret = pl111_connector_init(dev); + if (ret) { + dev_err(dev->dev, "Failed to create pl111_drm_connector\n"); + goto out_config; + } + + /* Don't actually attach if we didn't find a drm_panel + * attached to us. This will allow a kernel to include both + * the fbdev pl111 driver and this one, and choose between + * them based on which subsystem has support for the panel. + */ + if (!priv->connector.panel) { + dev_info(dev->dev, + "Disabling due to lack of DRM panel device.\n"); + ret = -ENODEV; + goto out_config; + } + + ret = pl111_display_init(dev); + if (ret != 0) { + dev_err(dev->dev, "Failed to init display\n"); + goto out_config; + } + + ret = drm_vblank_init(dev, 1); + if (ret != 0) { + dev_err(dev->dev, "Failed to init vblank\n"); + goto out_config; + } + + drm_mode_config_reset(dev); + + priv->fbdev = drm_fbdev_cma_init(dev, 32, + dev->mode_config.num_connector); + + drm_kms_helper_poll_init(dev); + + goto finish; + +out_config: + drm_mode_config_cleanup(dev); +finish: + return ret; +} + +DEFINE_DRM_GEM_CMA_FOPS(drm_fops); + +static void pl111_lastclose(struct drm_device *dev) +{ + struct pl111_drm_dev_private *priv = dev->dev_private; + + drm_fbdev_cma_restore_mode(priv->fbdev); +} + +static struct drm_driver pl111_drm_driver = { + .driver_features = + DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + .lastclose = pl111_lastclose, + .ioctls = NULL, + .fops = &drm_fops, + .name = "pl111", + .desc = DRIVER_DESC, + .date = "20170317", + .major = 1, + .minor = 0, + .patchlevel = 0, + .dumb_create = drm_gem_cma_dumb_create, + .dumb_destroy = drm_gem_dumb_destroy, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + .gem_free_object = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + + .enable_vblank = pl111_enable_vblank, + .disable_vblank = pl111_disable_vblank, + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = pl111_debugfs_init, +#endif +}; + +static int pl111_amba_probe(struct amba_device *amba_dev, + const struct amba_id *id) +{ + struct device *dev = &amba_dev->dev; + struct pl111_drm_dev_private *priv; + struct drm_device *drm; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + drm = drm_dev_alloc(&pl111_drm_driver, dev); + if (IS_ERR(drm)) + return PTR_ERR(drm); + amba_set_drvdata(amba_dev, drm); + priv->drm = drm; + drm->dev_private = priv; + + priv->regs = devm_ioremap_resource(dev, &amba_dev->res); + if (IS_ERR(priv->regs)) { + dev_err(dev, "%s failed mmio\n", __func__); + return PTR_ERR(priv->regs); + } + + /* turn off interrupts before requesting the irq */ + writel(0, priv->regs + CLCD_PL111_IENB); + + ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0, + "pl111", priv); + if (ret != 0) { + dev_err(dev, "%s failed irq %d\n", __func__, ret); + return ret; + } + + ret = pl111_modeset_init(drm); + if (ret != 0) + goto dev_unref; + + ret = drm_dev_register(drm, 0); + if (ret < 0) + goto dev_unref; + + return 0; + +dev_unref: + drm_dev_unref(drm); + return ret; +} + +static int pl111_amba_remove(struct amba_device *amba_dev) +{ + struct drm_device *drm = amba_get_drvdata(amba_dev); + struct pl111_drm_dev_private *priv = drm->dev_private; + + drm_dev_unregister(drm); + if (priv->fbdev) + drm_fbdev_cma_fini(priv->fbdev); + drm_mode_config_cleanup(drm); + drm_dev_unref(drm); + + return 0; +} + +static struct amba_id pl111_id_table[] = { + { + .id = 0x00041111, + .mask = 0x000fffff, + }, + {0, 0}, +}; + +static struct amba_driver pl111_amba_driver __maybe_unused = { + .drv = { + .name = "drm-clcd-pl111", + }, + .probe = pl111_amba_probe, + .remove = pl111_amba_remove, + .id_table = pl111_id_table, +}; + +#ifdef CONFIG_ARM_AMBA +module_amba_driver(pl111_amba_driver); +#endif + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("ARM Ltd."); +MODULE_LICENSE("GPL"); |