2 * Copyright (c) 2006-2009 Red Hat Inc.
3 * Copyright (c) 2006-2008 Intel Corporation
4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
6 * DRM framebuffer helper functions
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.
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
27 * Dave Airlie <airlied@linux.ie>
28 * Jesse Barnes <jesse.barnes@intel.com>
30 #include <linux/sysrq.h>
34 #include "drm_fb_helper.h"
35 #include "drm_crtc_helper.h"
37 MODULE_AUTHOR("David Airlie, Jesse Barnes");
38 MODULE_DESCRIPTION("DRM KMS helper");
39 MODULE_LICENSE("GPL and additional rights");
41 static LIST_HEAD(kernel_fb_helper_list);
43 int drm_fb_helper_add_connector(struct drm_connector *connector)
45 connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
46 if (!connector->fb_helper_private)
51 EXPORT_SYMBOL(drm_fb_helper_add_connector);
53 static int my_atoi(const char *name)
60 val = 10*val+(*name-'0');
69 * drm_fb_helper_connector_parse_command_line - parse command line for connector
70 * @connector - connector to parse line for
71 * @mode_option - per connector mode option
73 * This parses the connector specific then generic command lines for
74 * modes and options to configure the connector.
76 * This uses the same parameters as the fb modedb.c, except for extra
77 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
79 * enable/enable Digital/disable bit at the end
81 static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *connector,
82 const char *mode_option)
86 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
87 unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
88 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
90 enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
91 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
92 struct drm_fb_helper_cmdline_mode *cmdline_mode;
97 cmdline_mode = &fb_help_conn->cmdline_mode;
99 mode_option = fb_mode_option;
102 cmdline_mode->specified = false;
107 namelen = strlen(name);
108 for (i = namelen-1; i >= 0; i--) {
112 if (!refresh_specified && !bpp_specified &&
114 refresh = my_atoi(&name[i+1]);
115 refresh_specified = 1;
123 if (!bpp_specified && !yres_specified) {
124 bpp = my_atoi(&name[i+1]);
132 if (!yres_specified) {
133 yres = my_atoi(&name[i+1]);
156 force = DRM_FORCE_ON;
159 if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) ||
160 (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
161 force = DRM_FORCE_ON;
163 force = DRM_FORCE_ON_DIGITAL;
166 force = DRM_FORCE_OFF;
172 if (i < 0 && yres_specified) {
173 xres = my_atoi(name);
178 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
179 drm_get_connector_name(connector), xres, yres,
180 (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
181 "", (margins) ? " with margins" : "", (interlace) ?
187 case DRM_FORCE_OFF: s = "OFF"; break;
188 case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
190 case DRM_FORCE_ON: s = "ON"; break;
193 DRM_INFO("forcing %s connector %s\n",
194 drm_get_connector_name(connector), s);
195 connector->force = force;
199 cmdline_mode->specified = true;
200 cmdline_mode->xres = xres;
201 cmdline_mode->yres = yres;
204 if (refresh_specified) {
205 cmdline_mode->refresh_specified = true;
206 cmdline_mode->refresh = refresh;
210 cmdline_mode->bpp_specified = true;
211 cmdline_mode->bpp = bpp;
213 cmdline_mode->rb = rb ? true : false;
214 cmdline_mode->cvt = cvt ? true : false;
215 cmdline_mode->interlace = interlace ? true : false;
220 int drm_fb_helper_parse_command_line(struct drm_device *dev)
222 struct drm_connector *connector;
224 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
227 /* do something on return - turn off connector maybe */
228 if (fb_get_options(drm_get_connector_name(connector), &option))
231 drm_fb_helper_connector_parse_command_line(connector, option);
236 bool drm_fb_helper_force_kernel_mode(void)
239 bool ret, error = false;
240 struct drm_fb_helper *helper;
242 if (list_empty(&kernel_fb_helper_list))
245 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
246 for (i = 0; i < helper->crtc_count; i++) {
247 struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
248 ret = drm_crtc_helper_set_config(mode_set);
256 int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
259 DRM_ERROR("panic occurred, switching back to text console\n");
260 return drm_fb_helper_force_kernel_mode();
263 EXPORT_SYMBOL(drm_fb_helper_panic);
265 static struct notifier_block paniced = {
266 .notifier_call = drm_fb_helper_panic,
270 * drm_fb_helper_restore - restore the framebuffer console (kernel) config
272 * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
274 void drm_fb_helper_restore(void)
277 ret = drm_fb_helper_force_kernel_mode();
279 DRM_ERROR("Failed to restore crtc configuration\n");
281 EXPORT_SYMBOL(drm_fb_helper_restore);
283 #ifdef CONFIG_MAGIC_SYSRQ
284 static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
286 drm_fb_helper_restore();
288 static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
290 static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3)
292 schedule_work(&drm_fb_helper_restore_work);
295 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
296 .handler = drm_fb_helper_sysrq,
297 .help_msg = "force-fb(V)",
298 .action_msg = "Restore framebuffer console",
302 static void drm_fb_helper_on(struct fb_info *info)
304 struct drm_fb_helper *fb_helper = info->par;
305 struct drm_device *dev = fb_helper->dev;
306 struct drm_crtc *crtc;
307 struct drm_encoder *encoder;
311 * For each CRTC in this fb, turn the crtc on then,
312 * find all associated encoders and turn them on.
314 for (i = 0; i < fb_helper->crtc_count; i++) {
315 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
316 struct drm_crtc_helper_funcs *crtc_funcs =
317 crtc->helper_private;
319 /* Only mess with CRTCs in this fb */
320 if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
324 mutex_lock(&dev->mode_config.mutex);
325 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
326 mutex_unlock(&dev->mode_config.mutex);
328 /* Found a CRTC on this fb, now find encoders */
329 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
330 if (encoder->crtc == crtc) {
331 struct drm_encoder_helper_funcs *encoder_funcs;
333 encoder_funcs = encoder->helper_private;
334 mutex_lock(&dev->mode_config.mutex);
335 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
336 mutex_unlock(&dev->mode_config.mutex);
343 static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
345 struct drm_fb_helper *fb_helper = info->par;
346 struct drm_device *dev = fb_helper->dev;
347 struct drm_crtc *crtc;
348 struct drm_encoder *encoder;
352 * For each CRTC in this fb, find all associated encoders
353 * and turn them off, then turn off the CRTC.
355 for (i = 0; i < fb_helper->crtc_count; i++) {
356 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
357 struct drm_crtc_helper_funcs *crtc_funcs =
358 crtc->helper_private;
360 /* Only mess with CRTCs in this fb */
361 if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
365 /* Found a CRTC on this fb, now find encoders */
366 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
367 if (encoder->crtc == crtc) {
368 struct drm_encoder_helper_funcs *encoder_funcs;
370 encoder_funcs = encoder->helper_private;
371 mutex_lock(&dev->mode_config.mutex);
372 encoder_funcs->dpms(encoder, dpms_mode);
373 mutex_unlock(&dev->mode_config.mutex);
376 if (dpms_mode == DRM_MODE_DPMS_OFF) {
377 mutex_lock(&dev->mode_config.mutex);
378 crtc_funcs->dpms(crtc, dpms_mode);
379 mutex_unlock(&dev->mode_config.mutex);
385 int drm_fb_helper_blank(int blank, struct fb_info *info)
388 case FB_BLANK_UNBLANK:
389 drm_fb_helper_on(info);
391 case FB_BLANK_NORMAL:
392 drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
394 case FB_BLANK_HSYNC_SUSPEND:
395 drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
397 case FB_BLANK_VSYNC_SUSPEND:
398 drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
400 case FB_BLANK_POWERDOWN:
401 drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
406 EXPORT_SYMBOL(drm_fb_helper_blank);
408 static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
412 for (i = 0; i < helper->crtc_count; i++)
413 kfree(helper->crtc_info[i].mode_set.connectors);
414 kfree(helper->crtc_info);
417 int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn_count)
419 struct drm_device *dev = helper->dev;
420 struct drm_crtc *crtc;
424 helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
425 if (!helper->crtc_info)
428 helper->crtc_count = crtc_count;
430 for (i = 0; i < crtc_count; i++) {
431 helper->crtc_info[i].mode_set.connectors =
432 kcalloc(max_conn_count,
433 sizeof(struct drm_connector *),
436 if (!helper->crtc_info[i].mode_set.connectors) {
440 helper->crtc_info[i].mode_set.num_connectors = 0;
444 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
445 helper->crtc_info[i].crtc_id = crtc->base.id;
446 helper->crtc_info[i].mode_set.crtc = crtc;
449 helper->conn_limit = max_conn_count;
452 drm_fb_helper_crtc_free(helper);
455 EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
457 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
459 struct drm_fb_helper *fb_helper = info->par;
460 struct drm_device *dev = fb_helper->dev;
461 u16 *red, *green, *blue, *transp;
462 struct drm_crtc *crtc;
466 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
467 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
468 for (i = 0; i < fb_helper->crtc_count; i++) {
469 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
472 if (i == fb_helper->crtc_count)
478 transp = cmap->transp;
481 for (i = 0; i < cmap->len; i++) {
482 u16 hred, hgreen, hblue, htransp = 0xffff;
491 fb_helper->funcs->gamma_set(crtc, hred, hgreen, hblue, start++);
493 crtc_funcs->load_lut(crtc);
497 EXPORT_SYMBOL(drm_fb_helper_setcmap);
499 int drm_fb_helper_setcolreg(unsigned regno,
504 struct fb_info *info)
506 struct drm_fb_helper *fb_helper = info->par;
507 struct drm_device *dev = fb_helper->dev;
508 struct drm_crtc *crtc;
511 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
512 struct drm_framebuffer *fb = fb_helper->fb;
514 for (i = 0; i < fb_helper->crtc_count; i++) {
515 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
518 if (i == fb_helper->crtc_count)
524 if (fb->depth == 8) {
525 fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
530 u32 *pal = fb->pseudo_palette;
533 pal[regno] = ((red & 0xf800) >> 1) |
534 ((green & 0xf800) >> 6) |
535 ((blue & 0xf800) >> 11);
538 pal[regno] = (red & 0xf800) |
539 ((green & 0xfc00) >> 5) |
540 ((blue & 0xf800) >> 11);
545 (((red >> 8) & 0xff) << info->var.red.offset) |
546 (((green >> 8) & 0xff) << info->var.green.offset) |
547 (((blue >> 8) & 0xff) << info->var.blue.offset);
554 EXPORT_SYMBOL(drm_fb_helper_setcolreg);
556 int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
557 struct fb_info *info)
559 struct drm_fb_helper *fb_helper = info->par;
560 struct drm_framebuffer *fb = fb_helper->fb;
563 if (var->pixclock == -1 || !var->pixclock)
566 /* Need to resize the fb object !!! */
567 if (var->xres > fb->width || var->yres > fb->height) {
568 DRM_ERROR("Requested width/height is greater than current fb "
569 "object %dx%d > %dx%d\n", var->xres, var->yres,
570 fb->width, fb->height);
571 DRM_ERROR("Need resizing code.\n");
575 switch (var->bits_per_pixel) {
577 depth = (var->green.length == 6) ? 16 : 15;
580 depth = (var->transp.length > 0) ? 32 : 24;
583 depth = var->bits_per_pixel;
590 var->green.offset = 0;
591 var->blue.offset = 0;
593 var->green.length = 8;
594 var->blue.length = 8;
595 var->transp.length = 0;
596 var->transp.offset = 0;
599 var->red.offset = 10;
600 var->green.offset = 5;
601 var->blue.offset = 0;
603 var->green.length = 5;
604 var->blue.length = 5;
605 var->transp.length = 1;
606 var->transp.offset = 15;
609 var->red.offset = 11;
610 var->green.offset = 5;
611 var->blue.offset = 0;
613 var->green.length = 6;
614 var->blue.length = 5;
615 var->transp.length = 0;
616 var->transp.offset = 0;
619 var->red.offset = 16;
620 var->green.offset = 8;
621 var->blue.offset = 0;
623 var->green.length = 8;
624 var->blue.length = 8;
625 var->transp.length = 0;
626 var->transp.offset = 0;
629 var->red.offset = 16;
630 var->green.offset = 8;
631 var->blue.offset = 0;
633 var->green.length = 8;
634 var->blue.length = 8;
635 var->transp.length = 8;
636 var->transp.offset = 24;
643 EXPORT_SYMBOL(drm_fb_helper_check_var);
645 /* this will let fbcon do the mode init */
646 int drm_fb_helper_set_par(struct fb_info *info)
648 struct drm_fb_helper *fb_helper = info->par;
649 struct drm_device *dev = fb_helper->dev;
650 struct fb_var_screeninfo *var = &info->var;
651 struct drm_crtc *crtc;
655 if (var->pixclock != -1) {
656 DRM_ERROR("PIXEL CLCOK SET\n");
660 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
662 for (i = 0; i < fb_helper->crtc_count; i++) {
663 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
666 if (i == fb_helper->crtc_count)
669 if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) {
670 mutex_lock(&dev->mode_config.mutex);
671 ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set);
672 mutex_unlock(&dev->mode_config.mutex);
679 EXPORT_SYMBOL(drm_fb_helper_set_par);
681 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
682 struct fb_info *info)
684 struct drm_fb_helper *fb_helper = info->par;
685 struct drm_device *dev = fb_helper->dev;
686 struct drm_mode_set *modeset;
687 struct drm_crtc *crtc;
691 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
692 for (i = 0; i < fb_helper->crtc_count; i++) {
693 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
697 if (i == fb_helper->crtc_count)
700 modeset = &fb_helper->crtc_info[i].mode_set;
702 modeset->x = var->xoffset;
703 modeset->y = var->yoffset;
705 if (modeset->num_connectors) {
706 mutex_lock(&dev->mode_config.mutex);
707 ret = crtc->funcs->set_config(modeset);
708 mutex_unlock(&dev->mode_config.mutex);
710 info->var.xoffset = var->xoffset;
711 info->var.yoffset = var->yoffset;
717 EXPORT_SYMBOL(drm_fb_helper_pan_display);
719 int drm_fb_helper_single_fb_probe(struct drm_device *dev,
720 int (*fb_create)(struct drm_device *dev,
723 uint32_t surface_width,
724 uint32_t surface_height,
725 uint32_t surface_depth,
726 uint32_t surface_bpp,
727 struct drm_framebuffer **fb_ptr))
729 struct drm_crtc *crtc;
730 struct drm_connector *connector;
731 unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
732 unsigned int surface_width = 0, surface_height = 0;
735 int ret, i, conn_count = 0;
736 struct fb_info *info;
737 struct drm_framebuffer *fb;
738 struct drm_mode_set *modeset = NULL;
739 struct drm_fb_helper *fb_helper;
740 uint32_t surface_depth = 24, surface_bpp = 32;
742 /* first up get a count of crtcs now in use and new min/maxes width/heights */
743 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
744 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
746 struct drm_fb_helper_cmdline_mode *cmdline_mode;
751 cmdline_mode = &fb_help_conn->cmdline_mode;
753 if (cmdline_mode->bpp_specified) {
754 switch (cmdline_mode->bpp) {
756 surface_depth = surface_bpp = 8;
763 surface_depth = surface_bpp = 16;
766 surface_depth = surface_bpp = 24;
777 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
778 if (drm_helper_crtc_in_use(crtc)) {
779 if (crtc->desired_mode) {
780 if (crtc->desired_mode->hdisplay < fb_width)
781 fb_width = crtc->desired_mode->hdisplay;
783 if (crtc->desired_mode->vdisplay < fb_height)
784 fb_height = crtc->desired_mode->vdisplay;
786 if (crtc->desired_mode->hdisplay > surface_width)
787 surface_width = crtc->desired_mode->hdisplay;
789 if (crtc->desired_mode->vdisplay > surface_height)
790 surface_height = crtc->desired_mode->vdisplay;
796 if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
797 /* hmm everyone went away - assume VGA cable just fell out
798 and will come back later. */
802 /* do we have an fb already? */
803 if (list_empty(&dev->mode_config.fb_kernel_list)) {
804 ret = (*fb_create)(dev, fb_width, fb_height, surface_width,
805 surface_height, surface_depth, surface_bpp,
811 fb = list_first_entry(&dev->mode_config.fb_kernel_list,
812 struct drm_framebuffer, filp_head);
814 /* if someone hotplugs something bigger than we have already allocated, we are pwned.
815 As really we can't resize an fbdev that is in the wild currently due to fbdev
816 not really being designed for the lower layers moving stuff around under it.
817 - so in the grand style of things - punt. */
818 if ((fb->width < surface_width) ||
819 (fb->height < surface_height)) {
820 DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
826 fb_helper = info->par;
829 /* okay we need to setup new connector sets in the crtcs */
830 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
831 modeset = &fb_helper->crtc_info[crtc_count].mode_set;
834 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
835 if (connector->encoder)
836 if (connector->encoder->crtc == modeset->crtc) {
837 modeset->connectors[conn_count] = connector;
839 if (conn_count > fb_helper->conn_limit)
844 for (i = conn_count; i < fb_helper->conn_limit; i++)
845 modeset->connectors[i] = NULL;
847 modeset->crtc = crtc;
850 modeset->num_connectors = conn_count;
851 if (modeset->crtc->desired_mode) {
853 drm_mode_destroy(dev, modeset->mode);
854 modeset->mode = drm_mode_duplicate(dev,
855 modeset->crtc->desired_mode);
858 fb_helper->crtc_count = crtc_count;
862 info->var.pixclock = -1;
863 if (register_framebuffer(info) < 0)
866 drm_fb_helper_set_par(info);
868 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
871 /* Switch back to kernel console on panic */
872 /* multi card linked list maybe */
873 if (list_empty(&kernel_fb_helper_list)) {
874 printk(KERN_INFO "registered panic notifier\n");
875 atomic_notifier_chain_register(&panic_notifier_list,
877 register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
879 list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
882 EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
884 void drm_fb_helper_free(struct drm_fb_helper *helper)
886 list_del(&helper->kernel_fb_list);
887 if (list_empty(&kernel_fb_helper_list)) {
888 printk(KERN_INFO "unregistered panic notifier\n");
889 atomic_notifier_chain_unregister(&panic_notifier_list,
891 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
893 drm_fb_helper_crtc_free(helper);
895 EXPORT_SYMBOL(drm_fb_helper_free);
897 void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
900 info->fix.type = FB_TYPE_PACKED_PIXELS;
901 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
903 info->fix.type_aux = 0;
904 info->fix.xpanstep = 1; /* doing it in hw */
905 info->fix.ypanstep = 1; /* doing it in hw */
906 info->fix.ywrapstep = 0;
907 info->fix.accel = FB_ACCEL_NONE;
908 info->fix.type_aux = 0;
910 info->fix.line_length = pitch;
913 EXPORT_SYMBOL(drm_fb_helper_fill_fix);
915 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb,
916 uint32_t fb_width, uint32_t fb_height)
918 info->pseudo_palette = fb->pseudo_palette;
919 info->var.xres_virtual = fb->width;
920 info->var.yres_virtual = fb->height;
921 info->var.bits_per_pixel = fb->bits_per_pixel;
922 info->var.xoffset = 0;
923 info->var.yoffset = 0;
924 info->var.activate = FB_ACTIVATE_NOW;
925 info->var.height = -1;
926 info->var.width = -1;
930 info->var.red.offset = 0;
931 info->var.green.offset = 0;
932 info->var.blue.offset = 0;
933 info->var.red.length = 8; /* 8bit DAC */
934 info->var.green.length = 8;
935 info->var.blue.length = 8;
936 info->var.transp.offset = 0;
937 info->var.transp.length = 0;
940 info->var.red.offset = 10;
941 info->var.green.offset = 5;
942 info->var.blue.offset = 0;
943 info->var.red.length = 5;
944 info->var.green.length = 5;
945 info->var.blue.length = 5;
946 info->var.transp.offset = 15;
947 info->var.transp.length = 1;
950 info->var.red.offset = 11;
951 info->var.green.offset = 5;
952 info->var.blue.offset = 0;
953 info->var.red.length = 5;
954 info->var.green.length = 6;
955 info->var.blue.length = 5;
956 info->var.transp.offset = 0;
959 info->var.red.offset = 16;
960 info->var.green.offset = 8;
961 info->var.blue.offset = 0;
962 info->var.red.length = 8;
963 info->var.green.length = 8;
964 info->var.blue.length = 8;
965 info->var.transp.offset = 0;
966 info->var.transp.length = 0;
969 info->var.red.offset = 16;
970 info->var.green.offset = 8;
971 info->var.blue.offset = 0;
972 info->var.red.length = 8;
973 info->var.green.length = 8;
974 info->var.blue.length = 8;
975 info->var.transp.offset = 24;
976 info->var.transp.length = 8;
982 info->var.xres = fb_width;
983 info->var.yres = fb_height;
985 EXPORT_SYMBOL(drm_fb_helper_fill_var);