mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-08 12:14:47 +00:00
Removals:
- remove legacy dri1 drivers -
- i810, mga, r128, savage, sis, tdfx, via
New driver:
- intel VPU accelerator driver
- habanalabs comes via drm tree now
drm/core:
- use drm_dbg_ helpers in several places
- Document defaults for CRTC backgrounds
- Document use of drm_minor
edid:
- improve mode parsing and refactoring
connector:
- support analog TV mode property
media:
- add some common formats
udmabuf:
- add vmap/vunmap methods
fourcc:
- add XRGB1555 and RGB565 formats
- document open source user waiver
firmware:
- fix color-format selection for system framebuffer
format-helper:
- Add conversion from XRGB8888 to various sysfb formats
- Make XRGB8888 the only driver-emulated legacy format
- Add conversion from XRGB8888 to XBGR8888 and ABGR8888
fb-helper:
- fix preferred depth and bpp values across drivers
- Avoid blank consoles from selecting an incorrect color format
probe-helper:
- Enable/disable HPD on connectors
scheduler:
- Fix lockup in drm_sched_entity_kill()
- Deprecate drm_sched_resubmit_jobs()
bridge:
- remove unused functions
- implement i2c probe_new in various drivers
- ite-it6505: Locking fixes, Cache EDID data
- ite-it66121: Support IT6610 chip
- lontium-tl9611: Fix HDMI on DragonBoard 845c
- parade-ps8640: Use atomic bridge functions
- Support i.MX93 LDB plus DT bindings
debugfs:
- add per device helpers and convert drivers
displayport:
- mst fixes
- add DP adaptive sync DPCD definitions
fbdev:
- always pick 32bpp as default
- remove some unused code
simpledrm:
- support system memory framebuffers
panel:
- add orientation quirks for Lenovo Yoga Tab 3 X90F and DynaBook K50
- Use ktime_get_boottime() to measure power-down delay
- Fix auto-suspend delay
- Visionox VTDR6130 AMOLED DSI
- Support Himax HX8394
- Convert many drivers to common generic DSI write-sequence helper
- AUO A030JTN01
ttm:
- drop bo wait wrapper
- fix MIPS build
habanalabs:
- moved driver to accel subsystem
- gaudi2 decoder error improvement
- more trace events
- Gaudi2 abrupt reset by firmware support
- add uAPI to flush memory transactions
- add uAPI to pass through userspace reqs to fw
- remove dma-buf export by handle
amdgpu:
- add new INFO queries for peak and min sclk/mclk for profile modes
- Add PCIe info to the INFO IOCTL
- secure display support for multiple displays
- DML optimizations
- DCN 3.2 updates
- PSR updates
- DP 2.1 updates
- SR-IOV RAS updates
- VCN RAS support
- SMU 13.x updates
- Switch 1 element arrays to flexible arrays
- Add RAS support for DF 4.3
- Stack size improvements
- S0ix rework
- Allow 0 as a vram limit on APUs
- Handle profiling modes for SMU13.x
- Fix possible segfault in failure case
- Rework FW requests to happen in early_init for all IPs so
that we don't lose the sbios console if FW is missing
- Fix power reporting on certain firmwares for CZN/RN
- Allow S0ix without BIOS support
- Enable freesync over PCon
- Re-enable the AGP aperture on GMC 11.x
amdkfd:
- Error handling fixes
- PASID fixes
- Fix for cleared VRAM BOs
- Fix cleanup if GPUVM creation fails
- Memory accounting fix
- Use resource_size rather than open codeing it
- GC11 mGPU fix
radeon:
- Switch 1 element arrays to flexible arrays
- Fix memory leak on shutdown
- move to new logging
i915:
- Meteorlake display/OA/GSC fw/workarounds enabling
- DP MST DSC support
- Gamma/degamma readout support for the state checker
- Enable SDP split support for DP 2.0
- Add probe blocking support to i915.force_probe parameter
- Enable Xe HP 4tile support
- Avoid display direct calls to uncore
- Fix HuC delayed load memory leaks
- Add DG2 workarounds Wa_18018764978 and Wa_18019271663
- Improve suspend / resume times with VT-d scanout workaround active
- Fix DG2 visual corruption on small BAR systems by not forgetting to copy CCS aux state
- Fix TLB invalidation for Gen12.50 video and compute engines
- Enable HF-EEODB by switching HDMI, DP and LVDS to use struct drm_edid
- Start using unversioned DMC firmware paths for new platforms
- ELD refactor: Stop using hardware buffer, precompute ELD
- lots of display code refactoring
nouveau:
- drop legacy ioctl support
- replace 0-sized array
msm:
- dpu/dsi/mdss: Support for SM8350, SM8450 SM8550 and SC8280XP platform
- Added bindings for SM8150
- dpu: Partial support for DSC on SM8150 and SM8250
- dpu: Fixed color transformation matrix being lost on suspend/resume
- dp: Support SDM845 and SC8280XP platforms
- dp: Support for limiting DP link rate via DT property
- dsi: Validate display modes according to the DSI OPP table
- dsi: DSI PHY support for the SM6375 platform
- Add MSM_SUBMIT_BO_NO_IMPLICI
- a2xx: Support to load legacy firmware
- a6xx: GPU devcore dump updates for a650/a660
- GPU devfreq tuning and fixes
- Turn 8960 HDMI PHY into clock provider,
- Make 8960 HDMI PHY use PXO clock from DT
etnaviv:
- experimental versilicon NPU support
- report GPU load via fdinfo format
- MMU fault message improvements
tegra:
- rework syncpoint interrupt
mediatek:
- DSI timing fix
- fix config deps
ast:
- various fixes
exynos:
- restore bridge chain order fixes
gud:
- convert to shadow plane buffers
- perform flushing synchronously during atomic update
- Use new debugfs helpers
arm/hdlcd:
- Use new debugfs helper
ili9486:
- Support 16-bit pixel data
imx:
- Split off IPUv3 driver
mipi-dbi:
- convert to DRM shadow-plane helpers
- rsp driver changes
- Support separate I/O-voltage supply
mxsfb:
- Depend on ARCH_MXS or ARCH_MXC
sun4i:
- convert to new TV mode property
vc4:
- convert to new TV mode property
- kunit tests
- Support RGB565 and RGB666 formats
- convert dsi driver to bridge
- Various HVS an CRTC fixes
v3d:
- Do not opencode drm_gem_object_lookup()
virtio:
- improve tracing
vkms:
- support small cursors in IGT tests
- Fix SEGFAULT from incorrect GEM-buffer mapping
rcar-du:
- fixes and improvements
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmP2rKwACgkQDHTzWXnE
hr7cZw//WNBHajGXWUnuhh5GEd5QDiEzC5cazNT+QE9XFuv/ZT/AxchZ+v2zAYM7
uZ0VhRrWq7y2OZtNQjQ9LSTUE1vAjXwTH5roIKWQH4Xl4r2iPpqBMpvYppptOaoP
MEXqtTXAIjzxRPFFzXGuj4CnfsTUhLn8YM6roAJ+Q+banszxNL1XBPs8xO2isyko
6RFk4XHhIwhnL3GCCggNcxSQh2itZ6niytLXScO1YgoQ90eDVJl+RAEO14K10svL
Dq5tImbuwze06blM8xZxjDRtlNu/0n3Y1VC4oCDvEZHQFq7gfMk5rc1GpBAz9MUT
bBT9Ep4Q8Sp1xcyvxWSEDO8QV/C9y8Fr48CIfsJAxjtlLBuTvUZmSQI/jvoNeJmi
G3pFY6QmuEkl2W9uxPQusFlRVnPrlO0KFMORgxg9w95xqT9Rb2+F6dAauIjuiZLR
WgQPBy2wLxjxZek0am3U2b4B6EgPHLBEyfQge51Qh3EOL6rIZO3Yx+wAJVglTKRH
WzSyMRx0LQKyG4soE8P7V3KNBdsSgsjgq1I5fPyiJ4ck06d7jOD+BZVEfbAdz9Mi
eOxfCx3P83LCedKLfgQ652lc2BSgu+04N69/d06eNuSFbWgCl9Aw/4WmwGAQEP0w
B7w+Od20psq2ffEz7GwO8BP9c6K++a5PvlsvhiSYJqjkHndgcMY=
=HQUi
-----END PGP SIGNATURE-----
Merge tag 'drm-next-2023-02-23' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"There are a bunch of changes all over in the usual places.
Highlights:
- habanalabs moves from misc to accel
- first accel driver for Intel VPU (Versatile Processing Unit)
inference engine
- dropped all the ancient legacy DRI1 drivers. I think it's been at
least 10 years since anyone has heard about these.
- Intel DG2 updates and prelim Meteorlake enablement
- etnaviv adds support for Versilicon NPU device (a GPU like engine
with inference accelerators)
Detailed summary:
Removals:
- remove legacy dri1 drivers: i810, mga, r128, savage, sis, tdfx, via
New driver:
- intel VPU accelerator driver
- habanalabs comes via drm tree now
drm/core:
- use drm_dbg_ helpers in several places
- Document defaults for CRTC backgrounds
- Document use of drm_minor
edid:
- improve mode parsing and refactoring
connector:
- support analog TV mode property
media:
- add some common formats
udmabuf:
- add vmap/vunmap methods
fourcc:
- add XRGB1555 and RGB565 formats
- document open source user waiver
firmware:
- fix color-format selection for system framebuffer
format-helper:
- Add conversion from XRGB8888 to various sysfb formats
- Make XRGB8888 the only driver-emulated legacy format
- Add conversion from XRGB8888 to XBGR8888 and ABGR8888
fb-helper:
- fix preferred depth and bpp values across drivers
- Avoid blank consoles from selecting an incorrect color format
probe-helper:
- Enable/disable HPD on connectors
scheduler:
- Fix lockup in drm_sched_entity_kill()
- Deprecate drm_sched_resubmit_jobs()
bridge:
- remove unused functions
- implement i2c probe_new in various drivers
- ite-it6505: Locking fixes, Cache EDID data
- ite-it66121: Support IT6610 chip
- lontium-tl9611: Fix HDMI on DragonBoard 845c
- parade-ps8640: Use atomic bridge functions
- Support i.MX93 LDB plus DT bindings
debugfs:
- add per device helpers and convert drivers
displayport:
- mst fixes
- add DP adaptive sync DPCD definitions
fbdev:
- always pick 32bpp as default
- remove some unused code
simpledrm:
- support system memory framebuffers
panel:
- add orientation quirks for Lenovo Yoga Tab 3 X90F and DynaBook K50
- Use ktime_get_boottime() to measure power-down delay
- Fix auto-suspend delay
- Visionox VTDR6130 AMOLED DSI
- Support Himax HX8394
- Convert many drivers to common generic DSI write-sequence helper
- AUO A030JTN01
ttm:
- drop bo wait wrapper
- fix MIPS build
habanalabs:
- moved driver to accel subsystem
- gaudi2 decoder error improvement
- more trace events
- Gaudi2 abrupt reset by firmware support
- add uAPI to flush memory transactions
- add uAPI to pass through userspace reqs to fw
- remove dma-buf export by handle
amdgpu:
- add new INFO queries for peak and min sclk/mclk for profile modes
- Add PCIe info to the INFO IOCTL
- secure display support for multiple displays
- DML optimizations
- DCN 3.2 updates
- PSR updates
- DP 2.1 updates
- SR-IOV RAS updates
- VCN RAS support
- SMU 13.x updates
- Switch 1 element arrays to flexible arrays
- Add RAS support for DF 4.3
- Stack size improvements
- S0ix rework
- Allow 0 as a vram limit on APUs
- Handle profiling modes for SMU13.x
- Fix possible segfault in failure case
- Rework FW requests to happen in early_init for all IPs so that we
don't lose the sbios console if FW is missing
- Fix power reporting on certain firmwares for CZN/RN
- Allow S0ix without BIOS support
- Enable freesync over PCon
- Re-enable the AGP aperture on GMC 11.x
amdkfd:
- Error handling fixes
- PASID fixes
- Fix for cleared VRAM BOs
- Fix cleanup if GPUVM creation fails
- Memory accounting fix
- Use resource_size rather than open codeing it
- GC11 mGPU fix
radeon:
- Switch 1 element arrays to flexible arrays
- Fix memory leak on shutdown
- move to new logging
i915:
- Meteorlake display/OA/GSC fw/workarounds enabling
- DP MST DSC support
- Gamma/degamma readout support for the state checker
- Enable SDP split support for DP 2.0
- Add probe blocking support to i915.force_probe parameter
- Enable Xe HP 4tile support
- Avoid display direct calls to uncore
- Fix HuC delayed load memory leaks
- Add DG2 workarounds Wa_18018764978 and Wa_18019271663
- Improve suspend / resume times with VT-d scanout workaround active
- Fix DG2 visual corruption on small BAR systems by not forgetting to
copy CCS aux state
- Fix TLB invalidation for Gen12.50 video and compute engines
- Enable HF-EEODB by switching HDMI, DP and LVDS to use struct
drm_edid
- Start using unversioned DMC firmware paths for new platforms
- ELD refactor: Stop using hardware buffer, precompute ELD
- lots of display code refactoring
nouveau:
- drop legacy ioctl support
- replace 0-sized array
msm:
- dpu/dsi/mdss: Support for SM8350, SM8450 SM8550 and SC8280XP platform
- Added bindings for SM8150
- dpu: Partial support for DSC on SM8150 and SM8250
- dpu: Fixed color transformation matrix being lost on suspend/resume
- dp: Support SDM845 and SC8280XP platforms
- dp: Support for limiting DP link rate via DT property
- dsi: Validate display modes according to the DSI OPP table
- dsi: DSI PHY support for the SM6375 platform
- Add MSM_SUBMIT_BO_NO_IMPLICI
- a2xx: Support to load legacy firmware
- a6xx: GPU devcore dump updates for a650/a660
- GPU devfreq tuning and fixes
- Turn 8960 HDMI PHY into clock provider,
- Make 8960 HDMI PHY use PXO clock from DT
etnaviv:
- experimental versilicon NPU support
- report GPU load via fdinfo format
- MMU fault message improvements
tegra:
- rework syncpoint interrupt
mediatek:
- DSI timing fix
- fix config deps
ast:
- various fixes
exynos:
- restore bridge chain order fixes
gud:
- convert to shadow plane buffers
- perform flushing synchronously during atomic update
- Use new debugfs helpers
arm/hdlcd:
- Use new debugfs helper
ili9486:
- Support 16-bit pixel data
imx:
- Split off IPUv3 driver
mipi-dbi:
- convert to DRM shadow-plane helpers
- rsp driver changes
- Support separate I/O-voltage supply
mxsfb:
- Depend on ARCH_MXS or ARCH_MXC
sun4i:
- convert to new TV mode property
vc4:
- convert to new TV mode property
- kunit tests
- Support RGB565 and RGB666 formats
- convert dsi driver to bridge
- Various HVS an CRTC fixes
v3d:
- Do not opencode drm_gem_object_lookup()
virtio:
- improve tracing
vkms:
- support small cursors in IGT tests
- Fix SEGFAULT from incorrect GEM-buffer mapping
rcar-du:
- fixes and improvements"
* tag 'drm-next-2023-02-23' of git://anongit.freedesktop.org/drm/drm: (1455 commits)
msm/fbdev: fix unused variable warning with clang.
drm/fb-helper: Remove drm_fb_helper_unprepare() from drm_fb_helper_fini()
dma-buf: make kobj_type structure constant
drm/shmem-helper: Fix locking for drm_gem_shmem_get_pages_sgt()
drm/amd/display: disable SubVP + DRR to prevent underflow
drm/amd/display: Fail atomic_check early on normalize_zpos error
drm/amd/pm: avoid unaligned access warnings
drm/amd/display: avoid unaligned access warnings
drm/amd/display: Remove duplicate/repeating expressions
drm/amd/display: Remove duplicate/repeating expression
drm/amd/display: Make variables declaration inside ifdef guard
drm/amd/display: Fix excess arguments on kernel-doc
drm/amd/display: Add previously missing includes
drm/amd/amdgpu: Add function prototypes to headers
drm/amd/display: Add function prototypes to headers
drm/amd/display: Turn global functions into static
drm/amd/display: remove unused _calculate_degamma_curve function
drm/amd/display: remove unused func declaration from resource headers
drm/amd/display: unset initial value for tf since it's never used
drm/amd/display: camel case cleanup in color_gamma file
...
523 lines
14 KiB
C
523 lines
14 KiB
C
// SPDX-License-Identifier: GPL-2.0 or MIT
|
|
/*
|
|
* Copyright 2018 Noralf Trønnes
|
|
*/
|
|
|
|
#include <linux/iosys-map.h>
|
|
#include <linux/list.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include <drm/drm_client.h>
|
|
#include <drm/drm_debugfs.h>
|
|
#include <drm/drm_device.h>
|
|
#include <drm/drm_drv.h>
|
|
#include <drm/drm_file.h>
|
|
#include <drm/drm_fourcc.h>
|
|
#include <drm/drm_framebuffer.h>
|
|
#include <drm/drm_gem.h>
|
|
#include <drm/drm_mode.h>
|
|
#include <drm/drm_print.h>
|
|
|
|
#include "drm_crtc_internal.h"
|
|
#include "drm_internal.h"
|
|
|
|
/**
|
|
* DOC: overview
|
|
*
|
|
* This library provides support for clients running in the kernel like fbdev and bootsplash.
|
|
*
|
|
* GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
|
|
*/
|
|
|
|
static int drm_client_open(struct drm_client_dev *client)
|
|
{
|
|
struct drm_device *dev = client->dev;
|
|
struct drm_file *file;
|
|
|
|
file = drm_file_alloc(dev->primary);
|
|
if (IS_ERR(file))
|
|
return PTR_ERR(file);
|
|
|
|
mutex_lock(&dev->filelist_mutex);
|
|
list_add(&file->lhead, &dev->filelist_internal);
|
|
mutex_unlock(&dev->filelist_mutex);
|
|
|
|
client->file = file;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void drm_client_close(struct drm_client_dev *client)
|
|
{
|
|
struct drm_device *dev = client->dev;
|
|
|
|
mutex_lock(&dev->filelist_mutex);
|
|
list_del(&client->file->lhead);
|
|
mutex_unlock(&dev->filelist_mutex);
|
|
|
|
drm_file_free(client->file);
|
|
}
|
|
|
|
/**
|
|
* drm_client_init - Initialise a DRM client
|
|
* @dev: DRM device
|
|
* @client: DRM client
|
|
* @name: Client name
|
|
* @funcs: DRM client functions (optional)
|
|
*
|
|
* This initialises the client and opens a &drm_file.
|
|
* Use drm_client_register() to complete the process.
|
|
* The caller needs to hold a reference on @dev before calling this function.
|
|
* The client is freed when the &drm_device is unregistered. See drm_client_release().
|
|
*
|
|
* Returns:
|
|
* Zero on success or negative error code on failure.
|
|
*/
|
|
int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
|
|
const char *name, const struct drm_client_funcs *funcs)
|
|
{
|
|
int ret;
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET) || !dev->driver->dumb_create)
|
|
return -EOPNOTSUPP;
|
|
|
|
if (funcs && !try_module_get(funcs->owner))
|
|
return -ENODEV;
|
|
|
|
client->dev = dev;
|
|
client->name = name;
|
|
client->funcs = funcs;
|
|
|
|
ret = drm_client_modeset_create(client);
|
|
if (ret)
|
|
goto err_put_module;
|
|
|
|
ret = drm_client_open(client);
|
|
if (ret)
|
|
goto err_free;
|
|
|
|
drm_dev_get(dev);
|
|
|
|
return 0;
|
|
|
|
err_free:
|
|
drm_client_modeset_free(client);
|
|
err_put_module:
|
|
if (funcs)
|
|
module_put(funcs->owner);
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(drm_client_init);
|
|
|
|
/**
|
|
* drm_client_register - Register client
|
|
* @client: DRM client
|
|
*
|
|
* Add the client to the &drm_device client list to activate its callbacks.
|
|
* @client must be initialized by a call to drm_client_init(). After
|
|
* drm_client_register() it is no longer permissible to call drm_client_release()
|
|
* directly (outside the unregister callback), instead cleanup will happen
|
|
* automatically on driver unload.
|
|
*/
|
|
void drm_client_register(struct drm_client_dev *client)
|
|
{
|
|
struct drm_device *dev = client->dev;
|
|
|
|
mutex_lock(&dev->clientlist_mutex);
|
|
list_add(&client->list, &dev->clientlist);
|
|
mutex_unlock(&dev->clientlist_mutex);
|
|
}
|
|
EXPORT_SYMBOL(drm_client_register);
|
|
|
|
/**
|
|
* drm_client_release - Release DRM client resources
|
|
* @client: DRM client
|
|
*
|
|
* Releases resources by closing the &drm_file that was opened by drm_client_init().
|
|
* It is called automatically if the &drm_client_funcs.unregister callback is _not_ set.
|
|
*
|
|
* This function should only be called from the unregister callback. An exception
|
|
* is fbdev which cannot free the buffer if userspace has open file descriptors.
|
|
*
|
|
* Note:
|
|
* Clients cannot initiate a release by themselves. This is done to keep the code simple.
|
|
* The driver has to be unloaded before the client can be unloaded.
|
|
*/
|
|
void drm_client_release(struct drm_client_dev *client)
|
|
{
|
|
struct drm_device *dev = client->dev;
|
|
|
|
drm_dbg_kms(dev, "%s\n", client->name);
|
|
|
|
drm_client_modeset_free(client);
|
|
drm_client_close(client);
|
|
drm_dev_put(dev);
|
|
if (client->funcs)
|
|
module_put(client->funcs->owner);
|
|
}
|
|
EXPORT_SYMBOL(drm_client_release);
|
|
|
|
void drm_client_dev_unregister(struct drm_device *dev)
|
|
{
|
|
struct drm_client_dev *client, *tmp;
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
return;
|
|
|
|
mutex_lock(&dev->clientlist_mutex);
|
|
list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
|
|
list_del(&client->list);
|
|
if (client->funcs && client->funcs->unregister) {
|
|
client->funcs->unregister(client);
|
|
} else {
|
|
drm_client_release(client);
|
|
kfree(client);
|
|
}
|
|
}
|
|
mutex_unlock(&dev->clientlist_mutex);
|
|
}
|
|
|
|
/**
|
|
* drm_client_dev_hotplug - Send hotplug event to clients
|
|
* @dev: DRM device
|
|
*
|
|
* This function calls the &drm_client_funcs.hotplug callback on the attached clients.
|
|
*
|
|
* drm_kms_helper_hotplug_event() calls this function, so drivers that use it
|
|
* don't need to call this function themselves.
|
|
*/
|
|
void drm_client_dev_hotplug(struct drm_device *dev)
|
|
{
|
|
struct drm_client_dev *client;
|
|
int ret;
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
return;
|
|
|
|
if (!dev->mode_config.num_connector) {
|
|
drm_dbg_kms(dev, "No connectors found, will not send hotplug events!\n");
|
|
return;
|
|
}
|
|
|
|
mutex_lock(&dev->clientlist_mutex);
|
|
list_for_each_entry(client, &dev->clientlist, list) {
|
|
if (!client->funcs || !client->funcs->hotplug)
|
|
continue;
|
|
|
|
if (client->hotplug_failed)
|
|
continue;
|
|
|
|
ret = client->funcs->hotplug(client);
|
|
drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
|
|
if (ret)
|
|
client->hotplug_failed = true;
|
|
}
|
|
mutex_unlock(&dev->clientlist_mutex);
|
|
}
|
|
EXPORT_SYMBOL(drm_client_dev_hotplug);
|
|
|
|
void drm_client_dev_restore(struct drm_device *dev)
|
|
{
|
|
struct drm_client_dev *client;
|
|
int ret;
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
return;
|
|
|
|
mutex_lock(&dev->clientlist_mutex);
|
|
list_for_each_entry(client, &dev->clientlist, list) {
|
|
if (!client->funcs || !client->funcs->restore)
|
|
continue;
|
|
|
|
ret = client->funcs->restore(client);
|
|
drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
|
|
if (!ret) /* The first one to return zero gets the privilege to restore */
|
|
break;
|
|
}
|
|
mutex_unlock(&dev->clientlist_mutex);
|
|
}
|
|
|
|
static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
|
|
{
|
|
if (buffer->gem) {
|
|
drm_gem_vunmap_unlocked(buffer->gem, &buffer->map);
|
|
drm_gem_object_put(buffer->gem);
|
|
}
|
|
|
|
kfree(buffer);
|
|
}
|
|
|
|
static struct drm_client_buffer *
|
|
drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height,
|
|
u32 format, u32 *handle)
|
|
{
|
|
const struct drm_format_info *info = drm_format_info(format);
|
|
struct drm_mode_create_dumb dumb_args = { };
|
|
struct drm_device *dev = client->dev;
|
|
struct drm_client_buffer *buffer;
|
|
struct drm_gem_object *obj;
|
|
int ret;
|
|
|
|
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
|
if (!buffer)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
buffer->client = client;
|
|
|
|
dumb_args.width = width;
|
|
dumb_args.height = height;
|
|
dumb_args.bpp = drm_format_info_bpp(info, 0);
|
|
ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
|
|
if (ret)
|
|
goto err_delete;
|
|
|
|
obj = drm_gem_object_lookup(client->file, dumb_args.handle);
|
|
if (!obj) {
|
|
ret = -ENOENT;
|
|
goto err_delete;
|
|
}
|
|
|
|
buffer->pitch = dumb_args.pitch;
|
|
buffer->gem = obj;
|
|
*handle = dumb_args.handle;
|
|
|
|
return buffer;
|
|
|
|
err_delete:
|
|
drm_client_buffer_delete(buffer);
|
|
|
|
return ERR_PTR(ret);
|
|
}
|
|
|
|
/**
|
|
* drm_client_buffer_vmap - Map DRM client buffer into address space
|
|
* @buffer: DRM client buffer
|
|
* @map_copy: Returns the mapped memory's address
|
|
*
|
|
* This function maps a client buffer into kernel address space. If the
|
|
* buffer is already mapped, it returns the existing mapping's address.
|
|
*
|
|
* Client buffer mappings are not ref'counted. Each call to
|
|
* drm_client_buffer_vmap() should be followed by a call to
|
|
* drm_client_buffer_vunmap(); or the client buffer should be mapped
|
|
* throughout its lifetime.
|
|
*
|
|
* The returned address is a copy of the internal value. In contrast to
|
|
* other vmap interfaces, you don't need it for the client's vunmap
|
|
* function. So you can modify it at will during blit and draw operations.
|
|
*
|
|
* Returns:
|
|
* 0 on success, or a negative errno code otherwise.
|
|
*/
|
|
int
|
|
drm_client_buffer_vmap(struct drm_client_buffer *buffer,
|
|
struct iosys_map *map_copy)
|
|
{
|
|
struct iosys_map *map = &buffer->map;
|
|
int ret;
|
|
|
|
/*
|
|
* FIXME: The dependency on GEM here isn't required, we could
|
|
* convert the driver handle to a dma-buf instead and use the
|
|
* backend-agnostic dma-buf vmap support instead. This would
|
|
* require that the handle2fd prime ioctl is reworked to pull the
|
|
* fd_install step out of the driver backend hooks, to make that
|
|
* final step optional for internal users.
|
|
*/
|
|
ret = drm_gem_vmap_unlocked(buffer->gem, map);
|
|
if (ret)
|
|
return ret;
|
|
|
|
*map_copy = *map;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(drm_client_buffer_vmap);
|
|
|
|
/**
|
|
* drm_client_buffer_vunmap - Unmap DRM client buffer
|
|
* @buffer: DRM client buffer
|
|
*
|
|
* This function removes a client buffer's memory mapping. Calling this
|
|
* function is only required by clients that manage their buffer mappings
|
|
* by themselves.
|
|
*/
|
|
void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
|
|
{
|
|
struct iosys_map *map = &buffer->map;
|
|
|
|
drm_gem_vunmap_unlocked(buffer->gem, map);
|
|
}
|
|
EXPORT_SYMBOL(drm_client_buffer_vunmap);
|
|
|
|
static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
|
|
{
|
|
int ret;
|
|
|
|
if (!buffer->fb)
|
|
return;
|
|
|
|
ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
|
|
if (ret)
|
|
drm_err(buffer->client->dev,
|
|
"Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
|
|
|
|
buffer->fb = NULL;
|
|
}
|
|
|
|
static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
|
|
u32 width, u32 height, u32 format,
|
|
u32 handle)
|
|
{
|
|
struct drm_client_dev *client = buffer->client;
|
|
struct drm_mode_fb_cmd fb_req = { };
|
|
const struct drm_format_info *info;
|
|
int ret;
|
|
|
|
info = drm_format_info(format);
|
|
fb_req.bpp = drm_format_info_bpp(info, 0);
|
|
fb_req.depth = info->depth;
|
|
fb_req.width = width;
|
|
fb_req.height = height;
|
|
fb_req.handle = handle;
|
|
fb_req.pitch = buffer->pitch;
|
|
|
|
ret = drm_mode_addfb(client->dev, &fb_req, client->file);
|
|
if (ret)
|
|
return ret;
|
|
|
|
buffer->fb = drm_framebuffer_lookup(client->dev, buffer->client->file, fb_req.fb_id);
|
|
if (WARN_ON(!buffer->fb))
|
|
return -ENOENT;
|
|
|
|
/* drop the reference we picked up in framebuffer lookup */
|
|
drm_framebuffer_put(buffer->fb);
|
|
|
|
strscpy(buffer->fb->comm, client->name, TASK_COMM_LEN);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* drm_client_framebuffer_create - Create a client framebuffer
|
|
* @client: DRM client
|
|
* @width: Framebuffer width
|
|
* @height: Framebuffer height
|
|
* @format: Buffer format
|
|
*
|
|
* This function creates a &drm_client_buffer which consists of a
|
|
* &drm_framebuffer backed by a dumb buffer.
|
|
* Call drm_client_framebuffer_delete() to free the buffer.
|
|
*
|
|
* Returns:
|
|
* Pointer to a client buffer or an error pointer on failure.
|
|
*/
|
|
struct drm_client_buffer *
|
|
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
|
|
{
|
|
struct drm_client_buffer *buffer;
|
|
u32 handle;
|
|
int ret;
|
|
|
|
buffer = drm_client_buffer_create(client, width, height, format,
|
|
&handle);
|
|
if (IS_ERR(buffer))
|
|
return buffer;
|
|
|
|
ret = drm_client_buffer_addfb(buffer, width, height, format, handle);
|
|
|
|
/*
|
|
* The handle is only needed for creating the framebuffer, destroy it
|
|
* again to solve a circular dependency should anybody export the GEM
|
|
* object as DMA-buf. The framebuffer and our buffer structure are still
|
|
* holding references to the GEM object to prevent its destruction.
|
|
*/
|
|
drm_mode_destroy_dumb(client->dev, handle, client->file);
|
|
|
|
if (ret) {
|
|
drm_client_buffer_delete(buffer);
|
|
return ERR_PTR(ret);
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
EXPORT_SYMBOL(drm_client_framebuffer_create);
|
|
|
|
/**
|
|
* drm_client_framebuffer_delete - Delete a client framebuffer
|
|
* @buffer: DRM client buffer (can be NULL)
|
|
*/
|
|
void drm_client_framebuffer_delete(struct drm_client_buffer *buffer)
|
|
{
|
|
if (!buffer)
|
|
return;
|
|
|
|
drm_client_buffer_rmfb(buffer);
|
|
drm_client_buffer_delete(buffer);
|
|
}
|
|
EXPORT_SYMBOL(drm_client_framebuffer_delete);
|
|
|
|
/**
|
|
* drm_client_framebuffer_flush - Manually flush client framebuffer
|
|
* @buffer: DRM client buffer (can be NULL)
|
|
* @rect: Damage rectangle (if NULL flushes all)
|
|
*
|
|
* This calls &drm_framebuffer_funcs->dirty (if present) to flush buffer changes
|
|
* for drivers that need it.
|
|
*
|
|
* Returns:
|
|
* Zero on success or negative error code on failure.
|
|
*/
|
|
int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect)
|
|
{
|
|
if (!buffer || !buffer->fb || !buffer->fb->funcs->dirty)
|
|
return 0;
|
|
|
|
if (rect) {
|
|
struct drm_clip_rect clip = {
|
|
.x1 = rect->x1,
|
|
.y1 = rect->y1,
|
|
.x2 = rect->x2,
|
|
.y2 = rect->y2,
|
|
};
|
|
|
|
return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file,
|
|
0, 0, &clip, 1);
|
|
}
|
|
|
|
return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file,
|
|
0, 0, NULL, 0);
|
|
}
|
|
EXPORT_SYMBOL(drm_client_framebuffer_flush);
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
|
|
{
|
|
struct drm_debugfs_entry *entry = m->private;
|
|
struct drm_device *dev = entry->dev;
|
|
struct drm_printer p = drm_seq_file_printer(m);
|
|
struct drm_client_dev *client;
|
|
|
|
mutex_lock(&dev->clientlist_mutex);
|
|
list_for_each_entry(client, &dev->clientlist, list)
|
|
drm_printf(&p, "%s\n", client->name);
|
|
mutex_unlock(&dev->clientlist_mutex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct drm_debugfs_info drm_client_debugfs_list[] = {
|
|
{ "internal_clients", drm_client_debugfs_internal_clients, 0 },
|
|
};
|
|
|
|
void drm_client_debugfs_init(struct drm_minor *minor)
|
|
{
|
|
drm_debugfs_add_files(minor->dev, drm_client_debugfs_list,
|
|
ARRAY_SIZE(drm_client_debugfs_list));
|
|
}
|
|
#endif
|