/*1* Copyright (c) 2006-2009 Red Hat Inc.2* Copyright (c) 2006-2008 Intel Corporation3* Copyright (c) 2007 Dave Airlie <[email protected]>4*5* DRM framebuffer helper functions6*7* Permission to use, copy, modify, distribute, and sell this software and its8* documentation for any purpose is hereby granted without fee, provided that9* the above copyright notice appear in all copies and that both that copyright10* notice and this permission notice appear in supporting documentation, and11* that the name of the copyright holders not be used in advertising or12* publicity pertaining to distribution of the software without specific,13* written prior permission. The copyright holders make no representations14* about the suitability of this software for any purpose. It is provided "as15* is" without express or implied warranty.16*17* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,18* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO19* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR20* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,21* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER22* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE23* OF THIS SOFTWARE.24*25* Authors:26* Dave Airlie <[email protected]>27* Jesse Barnes <[email protected]>28*/29#ifndef DRM_FB_HELPER_H30#define DRM_FB_HELPER_H3132struct drm_clip_rect;33struct drm_fb_helper;3435#include <linux/fb.h>3637#include <drm/drm_client.h>3839/**40* struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size41* @fb_width: fbdev width42* @fb_height: fbdev height43* @surface_width: scanout buffer width44* @surface_height: scanout buffer height45* @surface_bpp: scanout buffer bpp46* @surface_depth: scanout buffer depth47*48* Note that the scanout surface width/height may be larger than the fbdev49* width/height. In case of multiple displays, the scanout surface is sized50* according to the largest width/height (so it is large enough for all CRTCs51* to scanout). But the fbdev width/height is sized to the minimum width/52* height of all the displays. This ensures that fbcon fits on the smallest53* of the attached displays. fb_width/fb_height is used by54* drm_fb_helper_fill_info() to fill out the &fb_info.var structure.55*/56struct drm_fb_helper_surface_size {57u32 fb_width;58u32 fb_height;59u32 surface_width;60u32 surface_height;61u32 surface_bpp;62u32 surface_depth;63};6465/**66* struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library67*68* Driver callbacks used by the fbdev emulation helper library.69*/70struct drm_fb_helper_funcs {71/**72* @fb_dirty:73*74* Driver callback to update the framebuffer memory. If set, fbdev75* emulation will invoke this callback in regular intervals after76* the framebuffer has been written.77*78* This callback is optional.79*80* Returns:81* 0 on success, or an error code otherwise.82*/83int (*fb_dirty)(struct drm_fb_helper *helper, struct drm_clip_rect *clip);8485/**86* @fb_restore:87*88* Driver callback to restore internal fbdev state. If set, fbdev89* emulation will invoke this callback after restoring the display90* mode.91*92* Only for i915. Do not use in new code.93*94* TODO: Fix i915 to not require this callback.95*/96void (*fb_restore)(struct drm_fb_helper *helper);9798/**99* @fb_set_suspend:100*101* Driver callback to suspend or resume, if set, fbdev emulation will102* invoke this callback during suspend and resume. Driver should call103* fb_set_suspend() from their implementation. If not set, fbdev104* emulation will invoke fb_set_suspend() directly.105*106* Only for i915. Do not use in new code.107*108* TODO: Fix i915 to not require this callback.109*/110void (*fb_set_suspend)(struct drm_fb_helper *helper, bool suspend);111};112113/**114* struct drm_fb_helper - main structure to emulate fbdev on top of KMS115* @fb: Scanout framebuffer object116* @dev: DRM device117* @funcs: driver callbacks for fb helper118* @info: emulated fbdev device info struct119* @pseudo_palette: fake palette of 16 colors120* @damage_clip: clip rectangle used with deferred_io to accumulate damage to121* the screen buffer122* @damage_lock: spinlock protecting @damage_clip123* @damage_work: worker used to flush the framebuffer124* @resume_work: worker used during resume if the console lock is already taken125*126* This is the main structure used by the fbdev helpers. Drivers supporting127* fbdev emulation should embedded this into their overall driver structure.128* Drivers must also fill out a &struct drm_fb_helper_funcs with a few129* operations.130*/131struct drm_fb_helper {132/**133* @client:134*135* DRM client used by the generic fbdev emulation.136*/137struct drm_client_dev client;138139/**140* @buffer:141*142* Framebuffer used by the generic fbdev emulation.143*/144struct drm_client_buffer *buffer;145146struct drm_framebuffer *fb;147struct drm_device *dev;148const struct drm_fb_helper_funcs *funcs;149struct fb_info *info;150u32 pseudo_palette[17];151struct drm_clip_rect damage_clip;152spinlock_t damage_lock;153struct work_struct damage_work;154struct work_struct resume_work;155156/**157* @lock:158*159* Top-level FBDEV helper lock. This protects all internal data160* structures and lists, such as @connector_info and @crtc_info.161*162* FIXME: fbdev emulation locking is a mess and long term we want to163* protect all helper internal state with this lock as well as reduce164* core KMS locking as much as possible.165*/166struct mutex lock;167168/**169* @kernel_fb_list:170*171* Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.172*/173struct list_head kernel_fb_list;174175/**176* @delayed_hotplug:177*178* A hotplug was received while fbdev wasn't in control of the DRM179* device, i.e. another KMS master was active. The output configuration180* needs to be reprobe when fbdev is in control again.181*/182bool delayed_hotplug;183184/**185* @deferred_setup:186*187* If no outputs are connected (disconnected or unknown) the FB helper188* code will defer setup until at least one of the outputs shows up.189* This field keeps track of the status so that setup can be retried190* at every hotplug event until it succeeds eventually.191*192* Protected by @lock.193*/194bool deferred_setup;195196/**197* @preferred_bpp:198*199* Temporary storage for the driver's preferred BPP setting passed to200* FB helper initialization. This needs to be tracked so that deferred201* FB helper setup can pass this on.202*203* See also: @deferred_setup204*/205int preferred_bpp;206207#ifdef CONFIG_FB_DEFERRED_IO208/**209* @fbdefio:210*211* Temporary storage for the driver's FB deferred I/O handler. If the212* driver uses the DRM fbdev emulation layer, this is set by the core213* to a generic deferred I/O handler if a driver is preferring to use214* a shadow buffer.215*/216struct fb_deferred_io fbdefio;217#endif218};219220static inline struct drm_fb_helper *221drm_fb_helper_from_client(struct drm_client_dev *client)222{223return container_of(client, struct drm_fb_helper, client);224}225226/**227* define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers228*229* Helper define to register default implementations of drm_fb_helper230* functions. To be used in struct fb_ops of drm drivers.231*/232#define DRM_FB_HELPER_DEFAULT_OPS \233.fb_check_var = drm_fb_helper_check_var, \234.fb_set_par = drm_fb_helper_set_par, \235.fb_setcmap = drm_fb_helper_setcmap, \236.fb_blank = drm_fb_helper_blank, \237.fb_pan_display = drm_fb_helper_pan_display, \238.fb_debug_enter = drm_fb_helper_debug_enter, \239.fb_debug_leave = drm_fb_helper_debug_leave, \240.fb_ioctl = drm_fb_helper_ioctl241242#ifdef CONFIG_DRM_FBDEV_EMULATION243void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,244unsigned int preferred_bpp,245const struct drm_fb_helper_funcs *funcs);246void drm_fb_helper_unprepare(struct drm_fb_helper *fb_helper);247int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *helper);248void drm_fb_helper_fini(struct drm_fb_helper *helper);249int drm_fb_helper_blank(int blank, struct fb_info *info);250int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,251struct fb_info *info);252int drm_fb_helper_set_par(struct fb_info *info);253int drm_fb_helper_check_var(struct fb_var_screeninfo *var,254struct fb_info *info);255256int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);257258struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper);259void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper);260void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper);261void drm_fb_helper_fill_info(struct fb_info *info,262struct drm_fb_helper *fb_helper,263struct drm_fb_helper_surface_size *sizes);264265void drm_fb_helper_damage_range(struct fb_info *info, off_t off, size_t len);266void drm_fb_helper_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height);267268#ifdef CONFIG_FB_DEFERRED_IO269void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist);270#endif271272void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);273void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,274bool suspend);275276int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);277278int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,279unsigned long arg);280281int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);282int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper);283int drm_fb_helper_debug_enter(struct fb_info *info);284int drm_fb_helper_debug_leave(struct fb_info *info);285void drm_fb_helper_lastclose(struct drm_device *dev);286#else287static inline void drm_fb_helper_prepare(struct drm_device *dev,288struct drm_fb_helper *helper,289unsigned int preferred_bpp,290const struct drm_fb_helper_funcs *funcs)291{292}293294static inline void drm_fb_helper_unprepare(struct drm_fb_helper *fb_helper)295{296}297298static inline int drm_fb_helper_init(struct drm_device *dev,299struct drm_fb_helper *helper)300{301/* So drivers can use it to free the struct */302helper->dev = dev;303dev->fb_helper = helper;304305return 0;306}307308static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)309{310if (helper && helper->dev)311helper->dev->fb_helper = NULL;312}313314static inline int drm_fb_helper_blank(int blank, struct fb_info *info)315{316return 0;317}318319static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,320struct fb_info *info)321{322return 0;323}324325static inline int drm_fb_helper_set_par(struct fb_info *info)326{327return 0;328}329330static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,331struct fb_info *info)332{333return 0;334}335336static inline int337drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)338{339return 0;340}341342static inline struct fb_info *343drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)344{345return NULL;346}347348static inline void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)349{350}351352static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)353{354}355356static inline void357drm_fb_helper_fill_info(struct fb_info *info,358struct drm_fb_helper *fb_helper,359struct drm_fb_helper_surface_size *sizes)360{361}362363static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,364struct fb_info *info)365{366return 0;367}368369static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,370unsigned long arg)371{372return 0;373}374375#ifdef CONFIG_FB_DEFERRED_IO376static inline void drm_fb_helper_deferred_io(struct fb_info *info,377struct list_head *pagelist)378{379}380#endif381382static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,383bool suspend)384{385}386387static inline void388drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)389{390}391392static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)393{394return 0;395}396397static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper)398{399return 0;400}401402static inline int drm_fb_helper_debug_enter(struct fb_info *info)403{404return 0;405}406407static inline int drm_fb_helper_debug_leave(struct fb_info *info)408{409return 0;410}411412static inline void drm_fb_helper_lastclose(struct drm_device *dev)413{414}415#endif416417#endif418419420