linux/include/drm/drm_fb_helper.h
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006-2009 Red Hat Inc.
   3 * Copyright (c) 2006-2008 Intel Corporation
   4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
   5 *
   6 * DRM framebuffer helper functions
   7 *
   8 * Permission to use, copy, modify, distribute, and sell this software and its
   9 * documentation for any purpose is hereby granted without fee, provided that
  10 * the above copyright notice appear in all copies and that both that copyright
  11 * notice and this permission notice appear in supporting documentation, and
  12 * that the name of the copyright holders not be used in advertising or
  13 * publicity pertaining to distribution of the software without specific,
  14 * written prior permission.  The copyright holders make no representations
  15 * about the suitability of this software for any purpose.  It is provided "as
  16 * is" without express or implied warranty.
  17 *
  18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  24 * OF THIS SOFTWARE.
  25 *
  26 * Authors:
  27 *      Dave Airlie <airlied@linux.ie>
  28 *      Jesse Barnes <jesse.barnes@intel.com>
  29 */
  30#ifndef DRM_FB_HELPER_H
  31#define DRM_FB_HELPER_H
  32
  33struct drm_fb_helper;
  34
  35#include <drm/drm_crtc.h>
  36#include <linux/kgdb.h>
  37
  38enum mode_set_atomic {
  39        LEAVE_ATOMIC_MODE_SET,
  40        ENTER_ATOMIC_MODE_SET,
  41};
  42
  43struct drm_fb_offset {
  44        int x, y;
  45};
  46
  47struct drm_fb_helper_crtc {
  48        struct drm_mode_set mode_set;
  49        struct drm_display_mode *desired_mode;
  50        int x, y;
  51};
  52
  53/**
  54 * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
  55 * @fb_width: fbdev width
  56 * @fb_height: fbdev height
  57 * @surface_width: scanout buffer width
  58 * @surface_height: scanout buffer height
  59 * @surface_bpp: scanout buffer bpp
  60 * @surface_depth: scanout buffer depth
  61 *
  62 * Note that the scanout surface width/height may be larger than the fbdev
  63 * width/height.  In case of multiple displays, the scanout surface is sized
  64 * according to the largest width/height (so it is large enough for all CRTCs
  65 * to scanout).  But the fbdev width/height is sized to the minimum width/
  66 * height of all the displays.  This ensures that fbcon fits on the smallest
  67 * of the attached displays.
  68 *
  69 * So what is passed to drm_fb_helper_fill_var() should be fb_width/fb_height,
  70 * rather than the surface size.
  71 */
  72struct drm_fb_helper_surface_size {
  73        u32 fb_width;
  74        u32 fb_height;
  75        u32 surface_width;
  76        u32 surface_height;
  77        u32 surface_bpp;
  78        u32 surface_depth;
  79};
  80
  81/**
  82 * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
  83 *
  84 * Driver callbacks used by the fbdev emulation helper library.
  85 */
  86struct drm_fb_helper_funcs {
  87        /**
  88         * @gamma_set:
  89         *
  90         * Set the given gamma LUT register on the given CRTC.
  91         *
  92         * This callback is optional.
  93         *
  94         * FIXME:
  95         *
  96         * This callback is functionally redundant with the core gamma table
  97         * support and simply exists because the fbdev hasn't yet been
  98         * refactored to use the core gamma table interfaces.
  99         */
 100        void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green,
 101                          u16 blue, int regno);
 102        /**
 103         * @gamma_get:
 104         *
 105         * Read the given gamma LUT register on the given CRTC, used to save the
 106         * current LUT when force-restoring the fbdev for e.g. kdbg.
 107         *
 108         * This callback is optional.
 109         *
 110         * FIXME:
 111         *
 112         * This callback is functionally redundant with the core gamma table
 113         * support and simply exists because the fbdev hasn't yet been
 114         * refactored to use the core gamma table interfaces.
 115         */
 116        void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green,
 117                          u16 *blue, int regno);
 118
 119        /**
 120         * @fb_probe:
 121         *
 122         * Driver callback to allocate and initialize the fbdev info structure.
 123         * Furthermore it also needs to allocate the DRM framebuffer used to
 124         * back the fbdev.
 125         *
 126         * This callback is mandatory.
 127         *
 128         * RETURNS:
 129         *
 130         * The driver should return 0 on success and a negative error code on
 131         * failure.
 132         */
 133        int (*fb_probe)(struct drm_fb_helper *helper,
 134                        struct drm_fb_helper_surface_size *sizes);
 135
 136        /**
 137         * @initial_config:
 138         *
 139         * Driver callback to setup an initial fbdev display configuration.
 140         * Drivers can use this callback to tell the fbdev emulation what the
 141         * preferred initial configuration is. This is useful to implement
 142         * smooth booting where the fbdev (and subsequently all userspace) never
 143         * changes the mode, but always inherits the existing configuration.
 144         *
 145         * This callback is optional.
 146         *
 147         * RETURNS:
 148         *
 149         * The driver should return true if a suitable initial configuration has
 150         * been filled out and false when the fbdev helper should fall back to
 151         * the default probing logic.
 152         */
 153        bool (*initial_config)(struct drm_fb_helper *fb_helper,
 154                               struct drm_fb_helper_crtc **crtcs,
 155                               struct drm_display_mode **modes,
 156                               struct drm_fb_offset *offsets,
 157                               bool *enabled, int width, int height);
 158};
 159
 160struct drm_fb_helper_connector {
 161        struct drm_connector *connector;
 162};
 163
 164/**
 165 * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
 166 * @fb: Scanout framebuffer object
 167 * @dev: DRM device
 168 * @crtc_count: number of possible CRTCs
 169 * @crtc_info: per-CRTC helper state (mode, x/y offset, etc)
 170 * @connector_count: number of connected connectors
 171 * @connector_info_alloc_count: size of connector_info
 172 * @connector_info: array of per-connector information
 173 * @funcs: driver callbacks for fb helper
 174 * @fbdev: emulated fbdev device info struct
 175 * @pseudo_palette: fake palette of 16 colors
 176 * @dirty_clip: clip rectangle used with deferred_io to accumulate damage to
 177 *              the screen buffer
 178 * @dirty_lock: spinlock protecting @dirty_clip
 179 * @dirty_work: worker used to flush the framebuffer
 180 * @resume_work: worker used during resume if the console lock is already taken
 181 *
 182 * This is the main structure used by the fbdev helpers. Drivers supporting
 183 * fbdev emulation should embedded this into their overall driver structure.
 184 * Drivers must also fill out a struct &drm_fb_helper_funcs with a few
 185 * operations.
 186 */
 187struct drm_fb_helper {
 188        struct drm_framebuffer *fb;
 189        struct drm_device *dev;
 190        int crtc_count;
 191        struct drm_fb_helper_crtc *crtc_info;
 192        int connector_count;
 193        int connector_info_alloc_count;
 194        struct drm_fb_helper_connector **connector_info;
 195        const struct drm_fb_helper_funcs *funcs;
 196        struct fb_info *fbdev;
 197        u32 pseudo_palette[17];
 198        struct drm_clip_rect dirty_clip;
 199        spinlock_t dirty_lock;
 200        struct work_struct dirty_work;
 201        struct work_struct resume_work;
 202
 203        /**
 204         * @kernel_fb_list:
 205         *
 206         * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
 207         */
 208        struct list_head kernel_fb_list;
 209
 210        /**
 211         * @delayed_hotplug:
 212         *
 213         * A hotplug was received while fbdev wasn't in control of the DRM
 214         * device, i.e. another KMS master was active. The output configuration
 215         * needs to be reprobe when fbdev is in control again.
 216         */
 217        bool delayed_hotplug;
 218};
 219
 220/**
 221 * define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
 222 *
 223 * Helper define to register default implementations of drm_fb_helper
 224 * functions. To be used in struct fb_ops of drm drivers.
 225 */
 226#define DRM_FB_HELPER_DEFAULT_OPS \
 227        .fb_check_var   = drm_fb_helper_check_var, \
 228        .fb_set_par     = drm_fb_helper_set_par, \
 229        .fb_setcmap     = drm_fb_helper_setcmap, \
 230        .fb_blank       = drm_fb_helper_blank, \
 231        .fb_pan_display = drm_fb_helper_pan_display
 232
 233#ifdef CONFIG_DRM_FBDEV_EMULATION
 234void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
 235                           const struct drm_fb_helper_funcs *funcs);
 236int drm_fb_helper_init(struct drm_device *dev,
 237                       struct drm_fb_helper *helper, int crtc_count,
 238                       int max_conn);
 239void drm_fb_helper_fini(struct drm_fb_helper *helper);
 240int drm_fb_helper_blank(int blank, struct fb_info *info);
 241int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
 242                              struct fb_info *info);
 243int drm_fb_helper_set_par(struct fb_info *info);
 244int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 245                            struct fb_info *info);
 246
 247int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
 248
 249struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
 250void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
 251void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper);
 252void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
 253                            uint32_t fb_width, uint32_t fb_height);
 254void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 255                            uint32_t depth);
 256
 257void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
 258
 259void drm_fb_helper_deferred_io(struct fb_info *info,
 260                               struct list_head *pagelist);
 261
 262ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
 263                               size_t count, loff_t *ppos);
 264ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
 265                                size_t count, loff_t *ppos);
 266
 267void drm_fb_helper_sys_fillrect(struct fb_info *info,
 268                                const struct fb_fillrect *rect);
 269void drm_fb_helper_sys_copyarea(struct fb_info *info,
 270                                const struct fb_copyarea *area);
 271void drm_fb_helper_sys_imageblit(struct fb_info *info,
 272                                 const struct fb_image *image);
 273
 274void drm_fb_helper_cfb_fillrect(struct fb_info *info,
 275                                const struct fb_fillrect *rect);
 276void drm_fb_helper_cfb_copyarea(struct fb_info *info,
 277                                const struct fb_copyarea *area);
 278void drm_fb_helper_cfb_imageblit(struct fb_info *info,
 279                                 const struct fb_image *image);
 280
 281void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
 282void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
 283                                        bool suspend);
 284
 285int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
 286
 287int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
 288int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 289int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
 290int drm_fb_helper_debug_enter(struct fb_info *info);
 291int drm_fb_helper_debug_leave(struct fb_info *info);
 292struct drm_display_mode *
 293drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
 294                        int width, int height);
 295struct drm_display_mode *
 296drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
 297                      int width, int height);
 298
 299int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
 300int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 301                                       struct drm_connector *connector);
 302#else
 303static inline void drm_fb_helper_prepare(struct drm_device *dev,
 304                                        struct drm_fb_helper *helper,
 305                                        const struct drm_fb_helper_funcs *funcs)
 306{
 307}
 308
 309static inline int drm_fb_helper_init(struct drm_device *dev,
 310                       struct drm_fb_helper *helper, int crtc_count,
 311                       int max_conn)
 312{
 313        return 0;
 314}
 315
 316static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
 317{
 318}
 319
 320static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
 321{
 322        return 0;
 323}
 324
 325static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
 326                                            struct fb_info *info)
 327{
 328        return 0;
 329}
 330
 331static inline int drm_fb_helper_set_par(struct fb_info *info)
 332{
 333        return 0;
 334}
 335
 336static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 337                                          struct fb_info *info)
 338{
 339        return 0;
 340}
 341
 342static inline int
 343drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
 344{
 345        return 0;
 346}
 347
 348static inline struct fb_info *
 349drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
 350{
 351        return NULL;
 352}
 353
 354static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
 355{
 356}
 357static inline void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
 358{
 359}
 360
 361static inline void drm_fb_helper_fill_var(struct fb_info *info,
 362                                          struct drm_fb_helper *fb_helper,
 363                                          uint32_t fb_width, uint32_t fb_height)
 364{
 365}
 366
 367static inline void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 368                                          uint32_t depth)
 369{
 370}
 371
 372static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
 373                                        struct fb_info *info)
 374{
 375        return 0;
 376}
 377
 378static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
 379{
 380}
 381
 382static inline void drm_fb_helper_deferred_io(struct fb_info *info,
 383                                             struct list_head *pagelist)
 384{
 385}
 386
 387static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
 388                                             char __user *buf, size_t count,
 389                                             loff_t *ppos)
 390{
 391        return -ENODEV;
 392}
 393
 394static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
 395                                              const char __user *buf,
 396                                              size_t count, loff_t *ppos)
 397{
 398        return -ENODEV;
 399}
 400
 401static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
 402                                              const struct fb_fillrect *rect)
 403{
 404}
 405
 406static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
 407                                              const struct fb_copyarea *area)
 408{
 409}
 410
 411static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
 412                                               const struct fb_image *image)
 413{
 414}
 415
 416static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
 417                                              const struct fb_fillrect *rect)
 418{
 419}
 420
 421static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
 422                                              const struct fb_copyarea *area)
 423{
 424}
 425
 426static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
 427                                               const struct fb_image *image)
 428{
 429}
 430
 431static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
 432                                             bool suspend)
 433{
 434}
 435
 436static inline void
 437drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
 438{
 439}
 440
 441static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 442{
 443        return 0;
 444}
 445
 446static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
 447                                               int bpp_sel)
 448{
 449        return 0;
 450}
 451
 452static inline int
 453drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
 454{
 455        return 0;
 456}
 457
 458static inline int drm_fb_helper_debug_enter(struct fb_info *info)
 459{
 460        return 0;
 461}
 462
 463static inline int drm_fb_helper_debug_leave(struct fb_info *info)
 464{
 465        return 0;
 466}
 467
 468static inline struct drm_display_mode *
 469drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
 470                       int width, int height)
 471{
 472        return NULL;
 473}
 474
 475static inline struct drm_display_mode *
 476drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
 477                      int width, int height)
 478{
 479        return NULL;
 480}
 481
 482static inline int
 483drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
 484                                struct drm_connector *connector)
 485{
 486        return 0;
 487}
 488
 489static inline int
 490drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 491                                   struct drm_connector *connector)
 492{
 493        return 0;
 494}
 495
 496#endif
 497
 498static inline int
 499drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
 500                                              const char *name, bool primary)
 501{
 502#if IS_REACHABLE(CONFIG_FB)
 503        return remove_conflicting_framebuffers(a, name, primary);
 504#else
 505        return 0;
 506#endif
 507}
 508
 509#endif
 510