/*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,257bool force);258259void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper);260void drm_fb_helper_fill_info(struct fb_info *info,261struct drm_fb_helper *fb_helper,262struct drm_fb_helper_surface_size *sizes);263264void drm_fb_helper_damage_range(struct fb_info *info, off_t off, size_t len);265void drm_fb_helper_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height);266267#ifdef CONFIG_FB_DEFERRED_IO268void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist);269#endif270271void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);272void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,273bool suspend);274275int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);276277int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,278unsigned long arg);279280int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);281int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper);282int drm_fb_helper_debug_enter(struct fb_info *info);283int drm_fb_helper_debug_leave(struct fb_info *info);284#else285static inline void drm_fb_helper_prepare(struct drm_device *dev,286struct drm_fb_helper *helper,287unsigned int preferred_bpp,288const struct drm_fb_helper_funcs *funcs)289{290}291292static inline void drm_fb_helper_unprepare(struct drm_fb_helper *fb_helper)293{294}295296static inline int drm_fb_helper_init(struct drm_device *dev,297struct drm_fb_helper *helper)298{299/* So drivers can use it to free the struct */300helper->dev = dev;301dev->fb_helper = helper;302303return 0;304}305306static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)307{308if (helper && helper->dev)309helper->dev->fb_helper = NULL;310}311312static inline int drm_fb_helper_blank(int blank, struct fb_info *info)313{314return 0;315}316317static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,318struct fb_info *info)319{320return 0;321}322323static inline int drm_fb_helper_set_par(struct fb_info *info)324{325return 0;326}327328static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,329struct fb_info *info)330{331return 0;332}333334static inline int335drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)336{337return 0;338}339340static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)341{342}343344static inline void345drm_fb_helper_fill_info(struct fb_info *info,346struct drm_fb_helper *fb_helper,347struct drm_fb_helper_surface_size *sizes)348{349}350351static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,352struct fb_info *info)353{354return 0;355}356357static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,358unsigned long arg)359{360return 0;361}362363#ifdef CONFIG_FB_DEFERRED_IO364static inline void drm_fb_helper_deferred_io(struct fb_info *info,365struct list_head *pagelist)366{367}368#endif369370static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,371bool suspend)372{373}374375static inline void376drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)377{378}379380static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)381{382return 0;383}384385static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper)386{387return 0;388}389390static inline int drm_fb_helper_debug_enter(struct fb_info *info)391{392return 0;393}394395static inline int drm_fb_helper_debug_leave(struct fb_info *info)396{397return 0;398}399#endif400401#endif402403404