Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
[sfrench/cifs-2.6.git] / include / drm / drm_fb_helper.h
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
33 struct drm_fb_helper;
34
35 #include <drm/drm_client.h>
36 #include <drm/drm_crtc.h>
37 #include <drm/drm_device.h>
38 #include <linux/kgdb.h>
39 #include <linux/vgaarb.h>
40
41 enum mode_set_atomic {
42         LEAVE_ATOMIC_MODE_SET,
43         ENTER_ATOMIC_MODE_SET,
44 };
45
46 /**
47  * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
48  * @fb_width: fbdev width
49  * @fb_height: fbdev height
50  * @surface_width: scanout buffer width
51  * @surface_height: scanout buffer height
52  * @surface_bpp: scanout buffer bpp
53  * @surface_depth: scanout buffer depth
54  *
55  * Note that the scanout surface width/height may be larger than the fbdev
56  * width/height.  In case of multiple displays, the scanout surface is sized
57  * according to the largest width/height (so it is large enough for all CRTCs
58  * to scanout).  But the fbdev width/height is sized to the minimum width/
59  * height of all the displays.  This ensures that fbcon fits on the smallest
60  * of the attached displays. fb_width/fb_height is used by
61  * drm_fb_helper_fill_info() to fill out the &fb_info.var structure.
62  */
63 struct drm_fb_helper_surface_size {
64         u32 fb_width;
65         u32 fb_height;
66         u32 surface_width;
67         u32 surface_height;
68         u32 surface_bpp;
69         u32 surface_depth;
70 };
71
72 /**
73  * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
74  *
75  * Driver callbacks used by the fbdev emulation helper library.
76  */
77 struct drm_fb_helper_funcs {
78         /**
79          * @fb_probe:
80          *
81          * Driver callback to allocate and initialize the fbdev info structure.
82          * Furthermore it also needs to allocate the DRM framebuffer used to
83          * back the fbdev.
84          *
85          * This callback is mandatory.
86          *
87          * RETURNS:
88          *
89          * The driver should return 0 on success and a negative error code on
90          * failure.
91          */
92         int (*fb_probe)(struct drm_fb_helper *helper,
93                         struct drm_fb_helper_surface_size *sizes);
94 };
95
96 /**
97  * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
98  * @fb: Scanout framebuffer object
99  * @dev: DRM device
100  * @funcs: driver callbacks for fb helper
101  * @fbdev: emulated fbdev device info struct
102  * @pseudo_palette: fake palette of 16 colors
103  * @dirty_clip: clip rectangle used with deferred_io to accumulate damage to
104  *              the screen buffer
105  * @dirty_lock: spinlock protecting @dirty_clip
106  * @dirty_work: worker used to flush the framebuffer
107  * @resume_work: worker used during resume if the console lock is already taken
108  *
109  * This is the main structure used by the fbdev helpers. Drivers supporting
110  * fbdev emulation should embedded this into their overall driver structure.
111  * Drivers must also fill out a &struct drm_fb_helper_funcs with a few
112  * operations.
113  */
114 struct drm_fb_helper {
115         /**
116          * @client:
117          *
118          * DRM client used by the generic fbdev emulation.
119          */
120         struct drm_client_dev client;
121
122         /**
123          * @buffer:
124          *
125          * Framebuffer used by the generic fbdev emulation.
126          */
127         struct drm_client_buffer *buffer;
128
129         struct drm_framebuffer *fb;
130         struct drm_device *dev;
131         const struct drm_fb_helper_funcs *funcs;
132         struct fb_info *fbdev;
133         u32 pseudo_palette[17];
134         struct drm_clip_rect dirty_clip;
135         spinlock_t dirty_lock;
136         struct work_struct dirty_work;
137         struct work_struct resume_work;
138
139         /**
140          * @lock:
141          *
142          * Top-level FBDEV helper lock. This protects all internal data
143          * structures and lists, such as @connector_info and @crtc_info.
144          *
145          * FIXME: fbdev emulation locking is a mess and long term we want to
146          * protect all helper internal state with this lock as well as reduce
147          * core KMS locking as much as possible.
148          */
149         struct mutex lock;
150
151         /**
152          * @kernel_fb_list:
153          *
154          * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
155          */
156         struct list_head kernel_fb_list;
157
158         /**
159          * @delayed_hotplug:
160          *
161          * A hotplug was received while fbdev wasn't in control of the DRM
162          * device, i.e. another KMS master was active. The output configuration
163          * needs to be reprobe when fbdev is in control again.
164          */
165         bool delayed_hotplug;
166
167         /**
168          * @deferred_setup:
169          *
170          * If no outputs are connected (disconnected or unknown) the FB helper
171          * code will defer setup until at least one of the outputs shows up.
172          * This field keeps track of the status so that setup can be retried
173          * at every hotplug event until it succeeds eventually.
174          *
175          * Protected by @lock.
176          */
177         bool deferred_setup;
178
179         /**
180          * @preferred_bpp:
181          *
182          * Temporary storage for the driver's preferred BPP setting passed to
183          * FB helper initialization. This needs to be tracked so that deferred
184          * FB helper setup can pass this on.
185          *
186          * See also: @deferred_setup
187          */
188         int preferred_bpp;
189 };
190
191 static inline struct drm_fb_helper *
192 drm_fb_helper_from_client(struct drm_client_dev *client)
193 {
194         return container_of(client, struct drm_fb_helper, client);
195 }
196
197 /**
198  * define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
199  *
200  * Helper define to register default implementations of drm_fb_helper
201  * functions. To be used in struct fb_ops of drm drivers.
202  */
203 #define DRM_FB_HELPER_DEFAULT_OPS \
204         .fb_check_var   = drm_fb_helper_check_var, \
205         .fb_set_par     = drm_fb_helper_set_par, \
206         .fb_setcmap     = drm_fb_helper_setcmap, \
207         .fb_blank       = drm_fb_helper_blank, \
208         .fb_pan_display = drm_fb_helper_pan_display, \
209         .fb_debug_enter = drm_fb_helper_debug_enter, \
210         .fb_debug_leave = drm_fb_helper_debug_leave, \
211         .fb_ioctl       = drm_fb_helper_ioctl
212
213 #ifdef CONFIG_DRM_FBDEV_EMULATION
214 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
215                            const struct drm_fb_helper_funcs *funcs);
216 int drm_fb_helper_init(struct drm_device *dev,
217                        struct drm_fb_helper *helper, int max_conn);
218 void drm_fb_helper_fini(struct drm_fb_helper *helper);
219 int drm_fb_helper_blank(int blank, struct fb_info *info);
220 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
221                               struct fb_info *info);
222 int drm_fb_helper_set_par(struct fb_info *info);
223 int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
224                             struct fb_info *info);
225
226 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
227
228 struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
229 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
230 void drm_fb_helper_fill_info(struct fb_info *info,
231                              struct drm_fb_helper *fb_helper,
232                              struct drm_fb_helper_surface_size *sizes);
233
234 void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
235
236 void drm_fb_helper_deferred_io(struct fb_info *info,
237                                struct list_head *pagelist);
238 int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper);
239
240 ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
241                                size_t count, loff_t *ppos);
242 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
243                                 size_t count, loff_t *ppos);
244
245 void drm_fb_helper_sys_fillrect(struct fb_info *info,
246                                 const struct fb_fillrect *rect);
247 void drm_fb_helper_sys_copyarea(struct fb_info *info,
248                                 const struct fb_copyarea *area);
249 void drm_fb_helper_sys_imageblit(struct fb_info *info,
250                                  const struct fb_image *image);
251
252 void drm_fb_helper_cfb_fillrect(struct fb_info *info,
253                                 const struct fb_fillrect *rect);
254 void drm_fb_helper_cfb_copyarea(struct fb_info *info,
255                                 const struct fb_copyarea *area);
256 void drm_fb_helper_cfb_imageblit(struct fb_info *info,
257                                  const struct fb_image *image);
258
259 void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
260 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
261                                         bool suspend);
262
263 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
264
265 int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
266                         unsigned long arg);
267
268 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
269 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
270 int drm_fb_helper_debug_enter(struct fb_info *info);
271 int drm_fb_helper_debug_leave(struct fb_info *info);
272
273 int drm_fb_helper_fbdev_setup(struct drm_device *dev,
274                               struct drm_fb_helper *fb_helper,
275                               const struct drm_fb_helper_funcs *funcs,
276                               unsigned int preferred_bpp,
277                               unsigned int max_conn_count);
278 void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
279
280 void drm_fb_helper_lastclose(struct drm_device *dev);
281 void drm_fb_helper_output_poll_changed(struct drm_device *dev);
282
283 int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
284                                 struct drm_fb_helper_surface_size *sizes);
285 int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
286 #else
287 static inline void drm_fb_helper_prepare(struct drm_device *dev,
288                                         struct drm_fb_helper *helper,
289                                         const struct drm_fb_helper_funcs *funcs)
290 {
291 }
292
293 static inline int drm_fb_helper_init(struct drm_device *dev,
294                        struct drm_fb_helper *helper,
295                        int max_conn)
296 {
297         /* So drivers can use it to free the struct */
298         helper->dev = dev;
299         dev->fb_helper = helper;
300
301         return 0;
302 }
303
304 static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
305 {
306         if (helper && helper->dev)
307                 helper->dev->fb_helper = NULL;
308 }
309
310 static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
311 {
312         return 0;
313 }
314
315 static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
316                                             struct fb_info *info)
317 {
318         return 0;
319 }
320
321 static inline int drm_fb_helper_set_par(struct fb_info *info)
322 {
323         return 0;
324 }
325
326 static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
327                                           struct fb_info *info)
328 {
329         return 0;
330 }
331
332 static inline int
333 drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
334 {
335         return 0;
336 }
337
338 static inline struct fb_info *
339 drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
340 {
341         return NULL;
342 }
343
344 static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
345 {
346 }
347
348 static inline void
349 drm_fb_helper_fill_info(struct fb_info *info,
350                         struct drm_fb_helper *fb_helper,
351                         struct drm_fb_helper_surface_size *sizes)
352 {
353 }
354
355 static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
356                                         struct fb_info *info)
357 {
358         return 0;
359 }
360
361 static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
362                                       unsigned long arg)
363 {
364         return 0;
365 }
366
367 static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
368 {
369 }
370
371 static inline void drm_fb_helper_deferred_io(struct fb_info *info,
372                                              struct list_head *pagelist)
373 {
374 }
375
376 static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
377 {
378         return -ENODEV;
379 }
380
381 static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
382                                              char __user *buf, size_t count,
383                                              loff_t *ppos)
384 {
385         return -ENODEV;
386 }
387
388 static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
389                                               const char __user *buf,
390                                               size_t count, loff_t *ppos)
391 {
392         return -ENODEV;
393 }
394
395 static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
396                                               const struct fb_fillrect *rect)
397 {
398 }
399
400 static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
401                                               const struct fb_copyarea *area)
402 {
403 }
404
405 static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
406                                                const struct fb_image *image)
407 {
408 }
409
410 static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
411                                               const struct fb_fillrect *rect)
412 {
413 }
414
415 static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
416                                               const struct fb_copyarea *area)
417 {
418 }
419
420 static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
421                                                const struct fb_image *image)
422 {
423 }
424
425 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
426                                              bool suspend)
427 {
428 }
429
430 static inline void
431 drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
432 {
433 }
434
435 static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
436 {
437         return 0;
438 }
439
440 static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
441                                                int bpp_sel)
442 {
443         return 0;
444 }
445
446 static inline int drm_fb_helper_debug_enter(struct fb_info *info)
447 {
448         return 0;
449 }
450
451 static inline int drm_fb_helper_debug_leave(struct fb_info *info)
452 {
453         return 0;
454 }
455
456 static inline int
457 drm_fb_helper_fbdev_setup(struct drm_device *dev,
458                           struct drm_fb_helper *fb_helper,
459                           const struct drm_fb_helper_funcs *funcs,
460                           unsigned int preferred_bpp,
461                           unsigned int max_conn_count)
462 {
463         /* So drivers can use it to free the struct */
464         dev->fb_helper = fb_helper;
465
466         return 0;
467 }
468
469 static inline void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
470 {
471         dev->fb_helper = NULL;
472 }
473
474 static inline void drm_fb_helper_lastclose(struct drm_device *dev)
475 {
476 }
477
478 static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
479 {
480 }
481
482 static inline int
483 drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
484                             struct drm_fb_helper_surface_size *sizes)
485 {
486         return 0;
487 }
488
489 static inline int
490 drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
491 {
492         return 0;
493 }
494
495 #endif
496
497 /* TODO: There's a todo entry to remove these three */
498 static inline int
499 drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
500 {
501         return 0;
502 }
503
504 static inline int
505 drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
506                                 struct drm_connector *connector)
507 {
508         return 0;
509 }
510
511 static inline int
512 drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
513                                    struct drm_connector *connector)
514 {
515         return 0;
516 }
517
518 /**
519  * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
520  * @a: memory range, users of which are to be removed
521  * @name: requesting driver name
522  * @primary: also kick vga16fb if present
523  *
524  * This function removes framebuffer devices (initialized by firmware/bootloader)
525  * which use memory range described by @a. If @a is NULL all such devices are
526  * removed.
527  */
528 static inline int
529 drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
530                                               const char *name, bool primary)
531 {
532 #if IS_REACHABLE(CONFIG_FB)
533         return remove_conflicting_framebuffers(a, name, primary);
534 #else
535         return 0;
536 #endif
537 }
538
539 /**
540  * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
541  * @pdev: PCI device
542  * @resource_id: index of PCI BAR configuring framebuffer memory
543  * @name: requesting driver name
544  *
545  * This function removes framebuffer devices (eg. initialized by firmware)
546  * using memory range configured for @pdev's BAR @resource_id.
547  *
548  * The function assumes that PCI device with shadowed ROM drives a primary
549  * display and so kicks out vga16fb.
550  */
551 static inline int
552 drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
553                                                   int resource_id,
554                                                   const char *name)
555 {
556         int ret = 0;
557
558         /*
559          * WARNING: Apparently we must kick fbdev drivers before vgacon,
560          * otherwise the vga fbdev driver falls over.
561          */
562 #if IS_REACHABLE(CONFIG_FB)
563         ret = remove_conflicting_pci_framebuffers(pdev, resource_id, name);
564 #endif
565         if (ret == 0)
566                 ret = vga_remove_vgacon(pdev);
567         return ret;
568 }
569
570 #endif