diff options
-rw-r--r-- | Documentation/DocBook/drm.tmpl | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 148 | ||||
-rw-r--r-- | include/drm/drm_fb_helper.h | 12 |
3 files changed, 146 insertions, 15 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index b26de523ab70..51e1904ac4c7 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl | |||
@@ -2143,6 +2143,7 @@ void intel_crt_init(struct drm_device *dev) | |||
2143 | <title>fbdev Helper Functions Reference</title> | 2143 | <title>fbdev Helper Functions Reference</title> |
2144 | !Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers | 2144 | !Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers |
2145 | !Edrivers/gpu/drm/drm_fb_helper.c | 2145 | !Edrivers/gpu/drm/drm_fb_helper.c |
2146 | !Iinclude/drm/drm_fb_helper.h | ||
2146 | </sect2> | 2147 | </sect2> |
2147 | <sect2> | 2148 | <sect2> |
2148 | <title>Display Port Helper Functions Reference</title> | 2149 | <title>Display Port Helper Functions Reference</title> |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e0d4b04c0eb5..94f304d8b795 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -52,9 +52,36 @@ static LIST_HEAD(kernel_fb_helper_list); | |||
52 | * mode setting driver. They can be used mostly independantely from the crtc | 52 | * mode setting driver. They can be used mostly independantely from the crtc |
53 | * helper functions used by many drivers to implement the kernel mode setting | 53 | * helper functions used by many drivers to implement the kernel mode setting |
54 | * interfaces. | 54 | * interfaces. |
55 | * | ||
56 | * Initialization is done as a three-step process with drm_fb_helper_init(), | ||
57 | * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). | ||
58 | * Drivers with fancier requirements than the default beheviour can override the | ||
59 | * second step with their own code. Teardown is done with drm_fb_helper_fini(). | ||
60 | * | ||
61 | * At runtime drivers should restore the fbdev console by calling | ||
62 | * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They | ||
63 | * should also notify the fb helper code from updates to the output | ||
64 | * configuration by calling drm_fb_helper_hotplug_event(). For easier | ||
65 | * integration with the output polling code in drm_crtc_helper.c the modeset | ||
66 | * code proves a ->output_poll_changed callback. | ||
67 | * | ||
68 | * All other functions exported by the fb helper library can be used to | ||
69 | * implement the fbdev driver interface by the driver. | ||
55 | */ | 70 | */ |
56 | 71 | ||
57 | /* simple single crtc case helper function */ | 72 | /** |
73 | * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev | ||
74 | * emulation helper | ||
75 | * @fb_helper: fbdev initialized with drm_fb_helper_init | ||
76 | * | ||
77 | * This functions adds all the available connectors for use with the given | ||
78 | * fb_helper. This is a separate step to allow drivers to freely assign | ||
79 | * connectors to the fbdev, e.g. if some are reserved for special purposes or | ||
80 | * not adequate to be used for the fbcon. | ||
81 | * | ||
82 | * Since this is part of the initial setup before the fbdev is published, no | ||
83 | * locking is required. | ||
84 | */ | ||
58 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) | 85 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) |
59 | { | 86 | { |
60 | struct drm_device *dev = fb_helper->dev; | 87 | struct drm_device *dev = fb_helper->dev; |
@@ -163,6 +190,10 @@ static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) | |||
163 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); | 190 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
164 | } | 191 | } |
165 | 192 | ||
193 | /** | ||
194 | * drm_fb_helper_debug_enter - implementation for ->fb_debug_enter | ||
195 | * @info: fbdev registered by the helper | ||
196 | */ | ||
166 | int drm_fb_helper_debug_enter(struct fb_info *info) | 197 | int drm_fb_helper_debug_enter(struct fb_info *info) |
167 | { | 198 | { |
168 | struct drm_fb_helper *helper = info->par; | 199 | struct drm_fb_helper *helper = info->par; |
@@ -208,6 +239,10 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) | |||
208 | return NULL; | 239 | return NULL; |
209 | } | 240 | } |
210 | 241 | ||
242 | /** | ||
243 | * drm_fb_helper_debug_leave - implementation for ->fb_debug_leave | ||
244 | * @info: fbdev registered by the helper | ||
245 | */ | ||
211 | int drm_fb_helper_debug_leave(struct fb_info *info) | 246 | int drm_fb_helper_debug_leave(struct fb_info *info) |
212 | { | 247 | { |
213 | struct drm_fb_helper *helper = info->par; | 248 | struct drm_fb_helper *helper = info->par; |
@@ -243,9 +278,9 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave); | |||
243 | * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration | 278 | * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration |
244 | * @fb_helper: fbcon to restore | 279 | * @fb_helper: fbcon to restore |
245 | * | 280 | * |
246 | * This should be called from driver's drm->lastclose callback when implementing | 281 | * This should be called from driver's drm ->lastclose callback |
247 | * an fbcon on top of kms using this helper. This ensures that the user isn't | 282 | * when implementing an fbcon on top of kms using this helper. This ensures that |
248 | * greeted with a black screen when e.g. X dies. | 283 | * the user isn't greeted with a black screen when e.g. X dies. |
249 | */ | 284 | */ |
250 | bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) | 285 | bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) |
251 | { | 286 | { |
@@ -381,6 +416,11 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) | |||
381 | drm_modeset_unlock_all(dev); | 416 | drm_modeset_unlock_all(dev); |
382 | } | 417 | } |
383 | 418 | ||
419 | /** | ||
420 | * drm_fb_helper_blank - implementation for ->fb_blank | ||
421 | * @blank: desired blanking state | ||
422 | * @info: fbdev registered by the helper | ||
423 | */ | ||
384 | int drm_fb_helper_blank(int blank, struct fb_info *info) | 424 | int drm_fb_helper_blank(int blank, struct fb_info *info) |
385 | { | 425 | { |
386 | switch (blank) { | 426 | switch (blank) { |
@@ -424,6 +464,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) | |||
424 | kfree(helper->crtc_info); | 464 | kfree(helper->crtc_info); |
425 | } | 465 | } |
426 | 466 | ||
467 | /** | ||
468 | * drm_fb_helper_init - initialize a drm_fb_helper structure | ||
469 | * @dev: drm device | ||
470 | * @fb_helper: driver-allocated fbdev helper structure to initialize | ||
471 | * @crtc_count: maximum number of crtcs to support in this fbdev emulation | ||
472 | * @max_conn_count: max connector count | ||
473 | * | ||
474 | * This allocates the structures for the fbdev helper with the given limits. | ||
475 | * Note that this won't yet touch the hardware (through the driver interfaces) | ||
476 | * nor register the fbdev. This is only done in drm_fb_helper_initial_config() | ||
477 | * to allow driver writes more control over the exact init sequence. | ||
478 | * | ||
479 | * Drivers must set fb_helper->funcs before calling | ||
480 | * drm_fb_helper_initial_config(). | ||
481 | * | ||
482 | * RETURNS: | ||
483 | * Zero if everything went ok, nonzero otherwise. | ||
484 | */ | ||
427 | int drm_fb_helper_init(struct drm_device *dev, | 485 | int drm_fb_helper_init(struct drm_device *dev, |
428 | struct drm_fb_helper *fb_helper, | 486 | struct drm_fb_helper *fb_helper, |
429 | int crtc_count, int max_conn_count) | 487 | int crtc_count, int max_conn_count) |
@@ -552,6 +610,11 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, | |||
552 | return 0; | 610 | return 0; |
553 | } | 611 | } |
554 | 612 | ||
613 | /** | ||
614 | * drm_fb_helper_setcmap - implementation for ->fb_setcmap | ||
615 | * @cmap: cmap to set | ||
616 | * @info: fbdev registered by the helper | ||
617 | */ | ||
555 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) | 618 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) |
556 | { | 619 | { |
557 | struct drm_fb_helper *fb_helper = info->par; | 620 | struct drm_fb_helper *fb_helper = info->par; |
@@ -591,6 +654,11 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) | |||
591 | } | 654 | } |
592 | EXPORT_SYMBOL(drm_fb_helper_setcmap); | 655 | EXPORT_SYMBOL(drm_fb_helper_setcmap); |
593 | 656 | ||
657 | /** | ||
658 | * drm_fb_helper_check_var - implementation for ->fb_check_var | ||
659 | * @var: screeninfo to check | ||
660 | * @info: fbdev registered by the helper | ||
661 | */ | ||
594 | int drm_fb_helper_check_var(struct fb_var_screeninfo *var, | 662 | int drm_fb_helper_check_var(struct fb_var_screeninfo *var, |
595 | struct fb_info *info) | 663 | struct fb_info *info) |
596 | { | 664 | { |
@@ -683,7 +751,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, | |||
683 | } | 751 | } |
684 | EXPORT_SYMBOL(drm_fb_helper_check_var); | 752 | EXPORT_SYMBOL(drm_fb_helper_check_var); |
685 | 753 | ||
686 | /* this will let fbcon do the mode init */ | 754 | /** |
755 | * drm_fb_helper_set_par - implementation for ->fb_set_par | ||
756 | * @info: fbdev registered by the helper | ||
757 | * | ||
758 | * This will let fbcon do the mode init and is called at initialization time by | ||
759 | * the fbdev core when registering the driver, and later on through the hotplug | ||
760 | * callback. | ||
761 | */ | ||
687 | int drm_fb_helper_set_par(struct fb_info *info) | 762 | int drm_fb_helper_set_par(struct fb_info *info) |
688 | { | 763 | { |
689 | struct drm_fb_helper *fb_helper = info->par; | 764 | struct drm_fb_helper *fb_helper = info->par; |
@@ -715,6 +790,11 @@ int drm_fb_helper_set_par(struct fb_info *info) | |||
715 | } | 790 | } |
716 | EXPORT_SYMBOL(drm_fb_helper_set_par); | 791 | EXPORT_SYMBOL(drm_fb_helper_set_par); |
717 | 792 | ||
793 | /** | ||
794 | * drm_fb_helper_pan_display - implementation for ->fb_pan_display | ||
795 | * @var: updated screen information | ||
796 | * @info: fbdev registered by the helper | ||
797 | */ | ||
718 | int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, | 798 | int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, |
719 | struct fb_info *info) | 799 | struct fb_info *info) |
720 | { | 800 | { |
@@ -753,8 +833,9 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, | |||
753 | EXPORT_SYMBOL(drm_fb_helper_pan_display); | 833 | EXPORT_SYMBOL(drm_fb_helper_pan_display); |
754 | 834 | ||
755 | /* | 835 | /* |
756 | * Allocates the backing storage through the ->fb_probe callback and then | 836 | * Allocates the backing storage and sets up the fbdev info structure through |
757 | * registers the fbdev and sets up the panic notifier. | 837 | * the ->fb_probe callback and then registers the fbdev and sets up the panic |
838 | * notifier. | ||
758 | */ | 839 | */ |
759 | static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, | 840 | static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, |
760 | int preferred_bpp) | 841 | int preferred_bpp) |
@@ -876,6 +957,19 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, | |||
876 | return 0; | 957 | return 0; |
877 | } | 958 | } |
878 | 959 | ||
960 | /** | ||
961 | * drm_fb_helper_fill_fix - initializes fixed fbdev information | ||
962 | * @info: fbdev registered by the helper | ||
963 | * @pitch: desired pitch | ||
964 | * @depth: desired depth | ||
965 | * | ||
966 | * Helper to fill in the fixed fbdev information useful for a non-accelerated | ||
967 | * fbdev emulations. Drivers which support acceleration methods which impose | ||
968 | * additional constraints need to set up their own limits. | ||
969 | * | ||
970 | * Drivers should call this (or their equivalent setup code) from their | ||
971 | * ->fb_probe callback. | ||
972 | */ | ||
879 | void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, | 973 | void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, |
880 | uint32_t depth) | 974 | uint32_t depth) |
881 | { | 975 | { |
@@ -896,6 +990,20 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, | |||
896 | } | 990 | } |
897 | EXPORT_SYMBOL(drm_fb_helper_fill_fix); | 991 | EXPORT_SYMBOL(drm_fb_helper_fill_fix); |
898 | 992 | ||
993 | /** | ||
994 | * drm_fb_helper_fill_var - initalizes variable fbdev information | ||
995 | * @info: fbdev instance to set up | ||
996 | * @fb_helper: fb helper instance to use as template | ||
997 | * @fb_width: desired fb width | ||
998 | * @fb_height: desired fb height | ||
999 | * | ||
1000 | * Sets up the variable fbdev metainformation from the given fb helper instance | ||
1001 | * and the drm framebuffer allocated in fb_helper->fb. | ||
1002 | * | ||
1003 | * Drivers should call this (or their equivalent setup code) from their | ||
1004 | * ->fb_probe callback after having allocated the fbdev backing | ||
1005 | * storage framebuffer. | ||
1006 | */ | ||
899 | void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, | 1007 | void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, |
900 | uint32_t fb_width, uint32_t fb_height) | 1008 | uint32_t fb_width, uint32_t fb_height) |
901 | { | 1009 | { |
@@ -1358,18 +1466,23 @@ out: | |||
1358 | } | 1466 | } |
1359 | 1467 | ||
1360 | /** | 1468 | /** |
1361 | * drm_helper_initial_config - setup a sane initial connector configuration | 1469 | * drm_fb_helper_initial_config - setup a sane initial connector configuration |
1362 | * @fb_helper: fb_helper device struct | 1470 | * @fb_helper: fb_helper device struct |
1363 | * @bpp_sel: bpp value to use for the framebuffer configuration | 1471 | * @bpp_sel: bpp value to use for the framebuffer configuration |
1364 | * | 1472 | * |
1365 | * LOCKING: | ||
1366 | * Called at init time by the driver to set up the @fb_helper initial | ||
1367 | * configuration, must take the mode config lock. | ||
1368 | * | ||
1369 | * Scans the CRTCs and connectors and tries to put together an initial setup. | 1473 | * Scans the CRTCs and connectors and tries to put together an initial setup. |
1370 | * At the moment, this is a cloned configuration across all heads with | 1474 | * At the moment, this is a cloned configuration across all heads with |
1371 | * a new framebuffer object as the backing store. | 1475 | * a new framebuffer object as the backing store. |
1372 | * | 1476 | * |
1477 | * Note that this also registers the fbdev and so allows userspace to call into | ||
1478 | * the driver through the fbdev interfaces. | ||
1479 | * | ||
1480 | * This function will call down into the ->fb_probe callback to let | ||
1481 | * the driver allocate and initialize the fbdev info structure and the drm | ||
1482 | * framebuffer used to back the fbdev. drm_fb_helper_fill_var() and | ||
1483 | * drm_fb_helper_fill_fix() are provided as helpers to setup simple default | ||
1484 | * values for the fbdev info structure. | ||
1485 | * | ||
1373 | * RETURNS: | 1486 | * RETURNS: |
1374 | * Zero if everything went ok, nonzero otherwise. | 1487 | * Zero if everything went ok, nonzero otherwise. |
1375 | */ | 1488 | */ |
@@ -1400,12 +1513,17 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); | |||
1400 | * probing all the outputs attached to the fb | 1513 | * probing all the outputs attached to the fb |
1401 | * @fb_helper: the drm_fb_helper | 1514 | * @fb_helper: the drm_fb_helper |
1402 | * | 1515 | * |
1403 | * LOCKING: | ||
1404 | * Called at runtime, must take mode config lock. | ||
1405 | * | ||
1406 | * Scan the connectors attached to the fb_helper and try to put together a | 1516 | * Scan the connectors attached to the fb_helper and try to put together a |
1407 | * setup after *notification of a change in output configuration. | 1517 | * setup after *notification of a change in output configuration. |
1408 | * | 1518 | * |
1519 | * Called at runtime, takes the mode config locks to be able to check/change the | ||
1520 | * modeset configuration. Must be run from process context (which usually means | ||
1521 | * either the output polling work or a work item launched from the driver's | ||
1522 | * hotplug interrupt). | ||
1523 | * | ||
1524 | * Note that the driver must ensure that this is only called _after_ the fb has | ||
1525 | * been fully set up, i.e. after the call to drm_fb_helper_initial_config. | ||
1526 | * | ||
1409 | * RETURNS: | 1527 | * RETURNS: |
1410 | * 0 on success and a non-zero error code otherwise. | 1528 | * 0 on success and a non-zero error code otherwise. |
1411 | */ | 1529 | */ |
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 973402d6effe..31e5b97c2e89 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
@@ -48,6 +48,18 @@ struct drm_fb_helper_surface_size { | |||
48 | u32 surface_depth; | 48 | u32 surface_depth; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /** | ||
52 | * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library | ||
53 | * @gamma_set: - Set the given gamma lut register on the given crtc. | ||
54 | * @gamma_get: - Read the given gamma lut register on the given crtc, used to | ||
55 | * save the current lut when force-restoring the fbdev for e.g. | ||
56 | * kdbg. | ||
57 | * @fb_probe: - Driver callback to allocate and initialize the fbdev info | ||
58 | * structure. Futhermore it also needs to allocate the drm | ||
59 | * framebuffer used to back the fbdev. | ||
60 | * | ||
61 | * Driver callbacks used by the fbdev emulation helper library. | ||
62 | */ | ||
51 | struct drm_fb_helper_funcs { | 63 | struct drm_fb_helper_funcs { |
52 | void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, | 64 | void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, |
53 | u16 blue, int regno); | 65 | u16 blue, int regno); |