Merge branches 'clk-samsung', 'clk-formatting', 'clk-si5341' and 'clk-socfpga' into...
[linux-2.6-microblaze.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_deferred_io(struct fb_info *info,
235                                struct list_head *pagelist);
236
237 ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
238                                size_t count, loff_t *ppos);
239 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
240                                 size_t count, loff_t *ppos);
241
242 void drm_fb_helper_sys_fillrect(struct fb_info *info,
243                                 const struct fb_fillrect *rect);
244 void drm_fb_helper_sys_copyarea(struct fb_info *info,
245                                 const struct fb_copyarea *area);
246 void drm_fb_helper_sys_imageblit(struct fb_info *info,
247                                  const struct fb_image *image);
248
249 void drm_fb_helper_cfb_fillrect(struct fb_info *info,
250                                 const struct fb_fillrect *rect);
251 void drm_fb_helper_cfb_copyarea(struct fb_info *info,
252                                 const struct fb_copyarea *area);
253 void drm_fb_helper_cfb_imageblit(struct fb_info *info,
254                                  const struct fb_image *image);
255
256 void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
257 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
258                                         bool suspend);
259
260 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
261
262 int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
263                         unsigned long arg);
264
265 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
266 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
267 int drm_fb_helper_debug_enter(struct fb_info *info);
268 int drm_fb_helper_debug_leave(struct fb_info *info);
269
270 void drm_fb_helper_lastclose(struct drm_device *dev);
271 void drm_fb_helper_output_poll_changed(struct drm_device *dev);
272
273 int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
274 #else
275 static inline void drm_fb_helper_prepare(struct drm_device *dev,
276                                         struct drm_fb_helper *helper,
277                                         const struct drm_fb_helper_funcs *funcs)
278 {
279 }
280
281 static inline int drm_fb_helper_init(struct drm_device *dev,
282                        struct drm_fb_helper *helper,
283                        int max_conn)
284 {
285         /* So drivers can use it to free the struct */
286         helper->dev = dev;
287         dev->fb_helper = helper;
288
289         return 0;
290 }
291
292 static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
293 {
294         if (helper && helper->dev)
295                 helper->dev->fb_helper = NULL;
296 }
297
298 static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
299 {
300         return 0;
301 }
302
303 static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
304                                             struct fb_info *info)
305 {
306         return 0;
307 }
308
309 static inline int drm_fb_helper_set_par(struct fb_info *info)
310 {
311         return 0;
312 }
313
314 static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
315                                           struct fb_info *info)
316 {
317         return 0;
318 }
319
320 static inline int
321 drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
322 {
323         return 0;
324 }
325
326 static inline struct fb_info *
327 drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
328 {
329         return NULL;
330 }
331
332 static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
333 {
334 }
335
336 static inline void
337 drm_fb_helper_fill_info(struct fb_info *info,
338                         struct drm_fb_helper *fb_helper,
339                         struct drm_fb_helper_surface_size *sizes)
340 {
341 }
342
343 static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
344                                         struct fb_info *info)
345 {
346         return 0;
347 }
348
349 static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
350                                       unsigned long arg)
351 {
352         return 0;
353 }
354
355 static inline void drm_fb_helper_deferred_io(struct fb_info *info,
356                                              struct list_head *pagelist)
357 {
358 }
359
360 static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
361 {
362         return -ENODEV;
363 }
364
365 static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
366                                              char __user *buf, size_t count,
367                                              loff_t *ppos)
368 {
369         return -ENODEV;
370 }
371
372 static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
373                                               const char __user *buf,
374                                               size_t count, loff_t *ppos)
375 {
376         return -ENODEV;
377 }
378
379 static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
380                                               const struct fb_fillrect *rect)
381 {
382 }
383
384 static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
385                                               const struct fb_copyarea *area)
386 {
387 }
388
389 static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
390                                                const struct fb_image *image)
391 {
392 }
393
394 static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
395                                               const struct fb_fillrect *rect)
396 {
397 }
398
399 static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
400                                               const struct fb_copyarea *area)
401 {
402 }
403
404 static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
405                                                const struct fb_image *image)
406 {
407 }
408
409 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
410                                              bool suspend)
411 {
412 }
413
414 static inline void
415 drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
416 {
417 }
418
419 static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
420 {
421         return 0;
422 }
423
424 static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
425                                                int bpp_sel)
426 {
427         return 0;
428 }
429
430 static inline int drm_fb_helper_debug_enter(struct fb_info *info)
431 {
432         return 0;
433 }
434
435 static inline int drm_fb_helper_debug_leave(struct fb_info *info)
436 {
437         return 0;
438 }
439
440 static inline void drm_fb_helper_lastclose(struct drm_device *dev)
441 {
442 }
443
444 static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
445 {
446 }
447
448 static inline int
449 drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
450 {
451         return 0;
452 }
453
454 #endif
455
456 /* TODO: There's a todo entry to remove these three */
457 static inline int
458 drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
459 {
460         return 0;
461 }
462
463 static inline int
464 drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
465                                 struct drm_connector *connector)
466 {
467         return 0;
468 }
469
470 static inline int
471 drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
472                                    struct drm_connector *connector)
473 {
474         return 0;
475 }
476
477 /**
478  * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
479  * @a: memory range, users of which are to be removed
480  * @name: requesting driver name
481  * @primary: also kick vga16fb if present
482  *
483  * This function removes framebuffer devices (initialized by firmware/bootloader)
484  * which use memory range described by @a. If @a is NULL all such devices are
485  * removed.
486  */
487 static inline int
488 drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
489                                               const char *name, bool primary)
490 {
491 #if IS_REACHABLE(CONFIG_FB)
492         return remove_conflicting_framebuffers(a, name, primary);
493 #else
494         return 0;
495 #endif
496 }
497
498 /**
499  * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
500  * @pdev: PCI device
501  * @name: requesting driver name
502  *
503  * This function removes framebuffer devices (eg. initialized by firmware)
504  * using memory range configured for any of @pdev's memory bars.
505  *
506  * The function assumes that PCI device with shadowed ROM drives a primary
507  * display and so kicks out vga16fb.
508  */
509 static inline int
510 drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
511                                                   const char *name)
512 {
513         int ret = 0;
514
515         /*
516          * WARNING: Apparently we must kick fbdev drivers before vgacon,
517          * otherwise the vga fbdev driver falls over.
518          */
519 #if IS_REACHABLE(CONFIG_FB)
520         ret = remove_conflicting_pci_framebuffers(pdev, name);
521 #endif
522         if (ret == 0)
523                 ret = vga_remove_vgacon(pdev);
524         return ret;
525 }
526
527 #endif