/* SPDX-License-Identifier: GPL-2.0 or MIT */12#ifndef _DRM_CLIENT_H_3#define _DRM_CLIENT_H_45#include <linux/iosys-map.h>6#include <linux/lockdep.h>7#include <linux/mutex.h>8#include <linux/types.h>910#include <drm/drm_connector.h>11#include <drm/drm_crtc.h>1213struct drm_client_dev;14struct drm_device;15struct drm_file;16struct drm_framebuffer;17struct drm_gem_object;18struct drm_minor;19struct module;2021/**22* struct drm_client_funcs - DRM client callbacks23*/24struct drm_client_funcs {25/**26* @owner: The module owner27*/28struct module *owner;2930/**31* @unregister:32*33* Called when &drm_device is unregistered. The client should respond by34* releasing its resources using drm_client_release().35*36* This callback is optional.37*/38void (*unregister)(struct drm_client_dev *client);3940/**41* @restore:42*43* Called on drm_lastclose(). The first client instance in the list that44* returns zero gets the privilege to restore and no more clients are45* called. This callback is not called after @unregister has been called.46*47* Note that the core does not guarantee exclusion against concurrent48* drm_open(). Clients need to ensure this themselves, for example by49* using drm_master_internal_acquire() and50* drm_master_internal_release().51*52* This callback is optional.53*/54int (*restore)(struct drm_client_dev *client);5556/**57* @hotplug:58*59* Called on drm_kms_helper_hotplug_event().60* This callback is not called after @unregister has been called.61*62* This callback is optional.63*/64int (*hotplug)(struct drm_client_dev *client);6566/**67* @suspend:68*69* Called when suspending the device.70*71* This callback is optional.72*73* FIXME: Some callers hold the console lock when invoking this74* function. This interferes with fbdev emulation, which75* also tries to acquire the lock. Push the console lock76* into the callback and remove 'holds_console_lock'.77*/78int (*suspend)(struct drm_client_dev *client, bool holds_console_lock);7980/**81* @resume:82*83* Called when resuming the device from suspend.84*85* This callback is optional.86*87* FIXME: Some callers hold the console lock when invoking this88* function. This interferes with fbdev emulation, which89* also tries to acquire the lock. Push the console lock90* into the callback and remove 'holds_console_lock'.91*/92int (*resume)(struct drm_client_dev *client, bool holds_console_lock);93};9495/**96* struct drm_client_dev - DRM client instance97*/98struct drm_client_dev {99/**100* @dev: DRM device101*/102struct drm_device *dev;103104/**105* @name: Name of the client.106*/107const char *name;108109/**110* @list:111*112* List of all clients of a DRM device, linked into113* &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.114*/115struct list_head list;116117/**118* @funcs: DRM client functions (optional)119*/120const struct drm_client_funcs *funcs;121122/**123* @file: DRM file124*/125struct drm_file *file;126127/**128* @modeset_mutex: Protects @modesets.129*/130struct mutex modeset_mutex;131132/**133* @modesets: CRTC configurations134*/135struct drm_mode_set *modesets;136137/**138* @suspended:139*140* The client has been suspended.141*/142bool suspended;143144/**145* @hotplug_pending:146*147* A hotplug event has been received while the client was suspended.148* Try again on resume.149*/150bool hotplug_pending;151152/**153* @hotplug_failed:154*155* Set by client hotplug helpers if the hotplugging failed156* before. It is usually not tried again.157*/158bool hotplug_failed;159};160161int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,162const char *name, const struct drm_client_funcs *funcs);163void drm_client_release(struct drm_client_dev *client);164void drm_client_register(struct drm_client_dev *client);165166/**167* struct drm_client_buffer - DRM client buffer168*/169struct drm_client_buffer {170/**171* @client: DRM client172*/173struct drm_client_dev *client;174175/**176* @pitch: Buffer pitch177*/178u32 pitch;179180/**181* @gem: GEM object backing this buffer182*183* FIXME: The dependency on GEM here isn't required, we could184* convert the driver handle to a dma-buf instead and use the185* backend-agnostic dma-buf vmap support instead. This would186* require that the handle2fd prime ioctl is reworked to pull the187* fd_install step out of the driver backend hooks, to make that188* final step optional for internal users.189*/190struct drm_gem_object *gem;191192/**193* @map: Virtual address for the buffer194*/195struct iosys_map map;196197/**198* @fb: DRM framebuffer199*/200struct drm_framebuffer *fb;201};202203struct drm_client_buffer *204drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);205void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);206int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect);207int drm_client_buffer_vmap_local(struct drm_client_buffer *buffer,208struct iosys_map *map_copy);209void drm_client_buffer_vunmap_local(struct drm_client_buffer *buffer);210int drm_client_buffer_vmap(struct drm_client_buffer *buffer,211struct iosys_map *map);212void drm_client_buffer_vunmap(struct drm_client_buffer *buffer);213214int drm_client_modeset_create(struct drm_client_dev *client);215void drm_client_modeset_free(struct drm_client_dev *client);216int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height);217bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation);218int drm_client_modeset_check(struct drm_client_dev *client);219int drm_client_modeset_commit_locked(struct drm_client_dev *client);220int drm_client_modeset_commit(struct drm_client_dev *client);221int drm_client_modeset_dpms(struct drm_client_dev *client, int mode);222223/**224* drm_client_for_each_modeset() - Iterate over client modesets225* @modeset: &drm_mode_set loop cursor226* @client: DRM client227*/228#define drm_client_for_each_modeset(modeset, client) \229for (({ lockdep_assert_held(&(client)->modeset_mutex); }), \230modeset = (client)->modesets; modeset->crtc; modeset++)231232/**233* drm_client_for_each_connector_iter - connector_list iterator macro234* @connector: &struct drm_connector pointer used as cursor235* @iter: &struct drm_connector_list_iter236*237* This iterates the connectors that are useable for internal clients (excludes238* writeback connectors).239*240* For more info see drm_for_each_connector_iter().241*/242#define drm_client_for_each_connector_iter(connector, iter) \243drm_for_each_connector_iter(connector, iter) \244if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)245246#endif247248249