]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/gpu/drm/drm_fb_helper.c
drm/radeon/kms: Get LVDS native mode details from EDID if necessary.
[net-next-2.6.git] / drivers / gpu / drm / drm_fb_helper.c
CommitLineData
785b93ef
DA
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#include <linux/sysrq.h>
31#include <linux/fb.h>
32#include "drmP.h"
33#include "drm_crtc.h"
34#include "drm_fb_helper.h"
35#include "drm_crtc_helper.h"
36
6fcefd56
DA
37MODULE_AUTHOR("David Airlie, Jesse Barnes");
38MODULE_DESCRIPTION("DRM KMS helper");
39MODULE_LICENSE("GPL and additional rights");
40
785b93ef
DA
41static LIST_HEAD(kernel_fb_helper_list);
42
43bool drm_fb_helper_force_kernel_mode(void)
44{
45 int i = 0;
46 bool ret, error = false;
47 struct drm_fb_helper *helper;
48
49 if (list_empty(&kernel_fb_helper_list))
50 return false;
51
52 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
53 for (i = 0; i < helper->crtc_count; i++) {
54 struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
55 ret = drm_crtc_helper_set_config(mode_set);
56 if (ret)
57 error = true;
58 }
59 }
60 return error;
61}
62
63int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
64 void *panic_str)
65{
66 DRM_ERROR("panic occurred, switching back to text console\n");
67 return drm_fb_helper_force_kernel_mode();
68 return 0;
69}
70EXPORT_SYMBOL(drm_fb_helper_panic);
71
72static struct notifier_block paniced = {
73 .notifier_call = drm_fb_helper_panic,
74};
75
76/**
77 * drm_fb_helper_restore - restore the framebuffer console (kernel) config
78 *
79 * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
80 */
81void drm_fb_helper_restore(void)
82{
83 bool ret;
84 ret = drm_fb_helper_force_kernel_mode();
85 if (ret == true)
86 DRM_ERROR("Failed to restore crtc configuration\n");
87}
88EXPORT_SYMBOL(drm_fb_helper_restore);
89
90static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
91{
92 drm_fb_helper_restore();
93}
94static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
95
96static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3)
97{
98 schedule_work(&drm_fb_helper_restore_work);
99}
100
101static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
102 .handler = drm_fb_helper_sysrq,
103 .help_msg = "force-fb(V)",
104 .action_msg = "Restore framebuffer console",
105};
106
107static void drm_fb_helper_on(struct fb_info *info)
108{
109 struct drm_fb_helper *fb_helper = info->par;
110 struct drm_device *dev = fb_helper->dev;
111 struct drm_crtc *crtc;
112 struct drm_encoder *encoder;
113 int i;
114
115 /*
116 * For each CRTC in this fb, turn the crtc on then,
117 * find all associated encoders and turn them on.
118 */
119 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
120 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
121
122 for (i = 0; i < fb_helper->crtc_count; i++) {
123 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
124 break;
125 }
126
127 mutex_lock(&dev->mode_config.mutex);
128 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
129 mutex_unlock(&dev->mode_config.mutex);
130
131 /* Found a CRTC on this fb, now find encoders */
132 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
133 if (encoder->crtc == crtc) {
134 struct drm_encoder_helper_funcs *encoder_funcs;
135
136 encoder_funcs = encoder->helper_private;
137 mutex_lock(&dev->mode_config.mutex);
138 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
139 mutex_unlock(&dev->mode_config.mutex);
140 }
141 }
142 }
143}
144
145static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
146{
147 struct drm_fb_helper *fb_helper = info->par;
148 struct drm_device *dev = fb_helper->dev;
149 struct drm_crtc *crtc;
150 struct drm_encoder *encoder;
151 int i;
152
153 /*
154 * For each CRTC in this fb, find all associated encoders
155 * and turn them off, then turn off the CRTC.
156 */
157 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
158 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
159
160 for (i = 0; i < fb_helper->crtc_count; i++) {
161 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
162 break;
163 }
164
165 /* Found a CRTC on this fb, now find encoders */
166 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
167 if (encoder->crtc == crtc) {
168 struct drm_encoder_helper_funcs *encoder_funcs;
169
170 encoder_funcs = encoder->helper_private;
171 mutex_lock(&dev->mode_config.mutex);
172 encoder_funcs->dpms(encoder, dpms_mode);
173 mutex_unlock(&dev->mode_config.mutex);
174 }
175 }
176 if (dpms_mode == DRM_MODE_DPMS_OFF) {
177 mutex_lock(&dev->mode_config.mutex);
178 crtc_funcs->dpms(crtc, dpms_mode);
179 mutex_unlock(&dev->mode_config.mutex);
180 }
181 }
182}
183
184int drm_fb_helper_blank(int blank, struct fb_info *info)
185{
186 switch (blank) {
187 case FB_BLANK_UNBLANK:
188 drm_fb_helper_on(info);
189 break;
190 case FB_BLANK_NORMAL:
191 drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
192 break;
193 case FB_BLANK_HSYNC_SUSPEND:
194 drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
195 break;
196 case FB_BLANK_VSYNC_SUSPEND:
197 drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
198 break;
199 case FB_BLANK_POWERDOWN:
200 drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
201 break;
202 }
203 return 0;
204}
205EXPORT_SYMBOL(drm_fb_helper_blank);
206
207static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
208{
209 int i;
210
211 for (i = 0; i < helper->crtc_count; i++)
212 kfree(helper->crtc_info[i].mode_set.connectors);
213 kfree(helper->crtc_info);
214}
215
216int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn_count)
217{
218 struct drm_device *dev = helper->dev;
219 struct drm_crtc *crtc;
220 int ret = 0;
221 int i;
222
223 helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
224 if (!helper->crtc_info)
225 return -ENOMEM;
226
227 helper->crtc_count = crtc_count;
228
229 for (i = 0; i < crtc_count; i++) {
230 helper->crtc_info[i].mode_set.connectors =
231 kcalloc(max_conn_count,
232 sizeof(struct drm_connector *),
233 GFP_KERNEL);
234
235 if (!helper->crtc_info[i].mode_set.connectors) {
236 ret = -ENOMEM;
237 goto out_free;
238 }
239 helper->crtc_info[i].mode_set.num_connectors = 0;
240 }
241
242 i = 0;
243 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
244 helper->crtc_info[i].crtc_id = crtc->base.id;
245 helper->crtc_info[i].mode_set.crtc = crtc;
246 i++;
247 }
248 helper->conn_limit = max_conn_count;
249 return 0;
250out_free:
251 drm_fb_helper_crtc_free(helper);
252 return -ENOMEM;
253}
254EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
255
256int drm_fb_helper_setcolreg(unsigned regno,
257 unsigned red,
258 unsigned green,
259 unsigned blue,
260 unsigned transp,
261 struct fb_info *info)
262{
263 struct drm_fb_helper *fb_helper = info->par;
264 struct drm_device *dev = fb_helper->dev;
265 struct drm_crtc *crtc;
266 int i;
267
268 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
269 struct drm_framebuffer *fb = fb_helper->fb;
270
271 for (i = 0; i < fb_helper->crtc_count; i++) {
272 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
273 break;
274 }
275 if (i == fb_helper->crtc_count)
276 continue;
277
278 if (regno > 255)
279 return 1;
280
281 if (fb->depth == 8) {
282 fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
283 return 0;
284 }
285
286 if (regno < 16) {
287 switch (fb->depth) {
288 case 15:
289 fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
290 ((green & 0xf800) >> 6) |
291 ((blue & 0xf800) >> 11);
292 break;
293 case 16:
294 fb->pseudo_palette[regno] = (red & 0xf800) |
295 ((green & 0xfc00) >> 5) |
296 ((blue & 0xf800) >> 11);
297 break;
298 case 24:
299 case 32:
300 fb->pseudo_palette[regno] =
301 (((red >> 8) & 0xff) << info->var.red.offset) |
302 (((green >> 8) & 0xff) << info->var.green.offset) |
303 (((blue >> 8) & 0xff) << info->var.blue.offset);
304 break;
305 }
306 }
307 }
308 return 0;
309}
310EXPORT_SYMBOL(drm_fb_helper_setcolreg);
311
312int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
313 struct fb_info *info)
314{
315 struct drm_fb_helper *fb_helper = info->par;
316 struct drm_framebuffer *fb = fb_helper->fb;
317 int depth;
318
319 if (var->pixclock == -1 || !var->pixclock)
320 return -EINVAL;
321
322 /* Need to resize the fb object !!! */
323 if (var->xres > fb->width || var->yres > fb->height) {
324 DRM_ERROR("Requested width/height is greater than current fb "
325 "object %dx%d > %dx%d\n", var->xres, var->yres,
326 fb->width, fb->height);
327 DRM_ERROR("Need resizing code.\n");
328 return -EINVAL;
329 }
330
331 switch (var->bits_per_pixel) {
332 case 16:
333 depth = (var->green.length == 6) ? 16 : 15;
334 break;
335 case 32:
336 depth = (var->transp.length > 0) ? 32 : 24;
337 break;
338 default:
339 depth = var->bits_per_pixel;
340 break;
341 }
342
343 switch (depth) {
344 case 8:
345 var->red.offset = 0;
346 var->green.offset = 0;
347 var->blue.offset = 0;
348 var->red.length = 8;
349 var->green.length = 8;
350 var->blue.length = 8;
351 var->transp.length = 0;
352 var->transp.offset = 0;
353 break;
354 case 15:
355 var->red.offset = 10;
356 var->green.offset = 5;
357 var->blue.offset = 0;
358 var->red.length = 5;
359 var->green.length = 5;
360 var->blue.length = 5;
361 var->transp.length = 1;
362 var->transp.offset = 15;
363 break;
364 case 16:
365 var->red.offset = 11;
366 var->green.offset = 5;
367 var->blue.offset = 0;
368 var->red.length = 5;
369 var->green.length = 6;
370 var->blue.length = 5;
371 var->transp.length = 0;
372 var->transp.offset = 0;
373 break;
374 case 24:
375 var->red.offset = 16;
376 var->green.offset = 8;
377 var->blue.offset = 0;
378 var->red.length = 8;
379 var->green.length = 8;
380 var->blue.length = 8;
381 var->transp.length = 0;
382 var->transp.offset = 0;
383 break;
384 case 32:
385 var->red.offset = 16;
386 var->green.offset = 8;
387 var->blue.offset = 0;
388 var->red.length = 8;
389 var->green.length = 8;
390 var->blue.length = 8;
391 var->transp.length = 8;
392 var->transp.offset = 24;
393 break;
394 default:
395 return -EINVAL;
396 }
397 return 0;
398}
399EXPORT_SYMBOL(drm_fb_helper_check_var);
400
401/* this will let fbcon do the mode init */
402int drm_fb_helper_set_par(struct fb_info *info)
403{
404 struct drm_fb_helper *fb_helper = info->par;
405 struct drm_device *dev = fb_helper->dev;
406 struct fb_var_screeninfo *var = &info->var;
407 struct drm_crtc *crtc;
408 int ret;
409 int i;
410
411 if (var->pixclock != -1) {
412 DRM_ERROR("PIXEL CLCOK SET\n");
413 return -EINVAL;
414 }
415
416 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
417
418 for (i = 0; i < fb_helper->crtc_count; i++) {
419 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
420 break;
421 }
422 if (i == fb_helper->crtc_count)
423 continue;
424
425 if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) {
426 mutex_lock(&dev->mode_config.mutex);
427 ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set);
428 mutex_unlock(&dev->mode_config.mutex);
429 if (ret)
430 return ret;
431 }
432 }
433 return 0;
434}
435EXPORT_SYMBOL(drm_fb_helper_set_par);
436
437int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
438 struct fb_info *info)
439{
440 struct drm_fb_helper *fb_helper = info->par;
441 struct drm_device *dev = fb_helper->dev;
442 struct drm_mode_set *modeset;
443 struct drm_crtc *crtc;
444 int ret = 0;
445 int i;
446
447 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
448 for (i = 0; i < fb_helper->crtc_count; i++) {
449 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
450 break;
451 }
452
453 if (i == fb_helper->crtc_count)
454 continue;
455
456 modeset = &fb_helper->crtc_info[i].mode_set;
457
458 modeset->x = var->xoffset;
459 modeset->y = var->yoffset;
460
461 if (modeset->num_connectors) {
462 mutex_lock(&dev->mode_config.mutex);
463 ret = crtc->funcs->set_config(modeset);
464 mutex_unlock(&dev->mode_config.mutex);
465 if (!ret) {
466 info->var.xoffset = var->xoffset;
467 info->var.yoffset = var->yoffset;
468 }
469 }
470 }
471 return ret;
472}
473EXPORT_SYMBOL(drm_fb_helper_pan_display);
474
475int drm_fb_helper_single_fb_probe(struct drm_device *dev,
476 int (*fb_create)(struct drm_device *dev,
477 uint32_t fb_width,
478 uint32_t fb_height,
479 uint32_t surface_width,
480 uint32_t surface_height,
481 struct drm_framebuffer **fb_ptr))
482{
483 struct drm_crtc *crtc;
484 struct drm_connector *connector;
485 unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
486 unsigned int surface_width = 0, surface_height = 0;
487 int new_fb = 0;
488 int crtc_count = 0;
489 int ret, i, conn_count = 0;
490 struct fb_info *info;
491 struct drm_framebuffer *fb;
492 struct drm_mode_set *modeset = NULL;
493 struct drm_fb_helper *fb_helper;
494
495 /* first up get a count of crtcs now in use and new min/maxes width/heights */
496 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
497 if (drm_helper_crtc_in_use(crtc)) {
498 if (crtc->desired_mode) {
499 if (crtc->desired_mode->hdisplay < fb_width)
500 fb_width = crtc->desired_mode->hdisplay;
501
502 if (crtc->desired_mode->vdisplay < fb_height)
503 fb_height = crtc->desired_mode->vdisplay;
504
505 if (crtc->desired_mode->hdisplay > surface_width)
506 surface_width = crtc->desired_mode->hdisplay;
507
508 if (crtc->desired_mode->vdisplay > surface_height)
509 surface_height = crtc->desired_mode->vdisplay;
510 }
511 crtc_count++;
512 }
513 }
514
515 if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
516 /* hmm everyone went away - assume VGA cable just fell out
517 and will come back later. */
518 return 0;
519 }
520
521 /* do we have an fb already? */
522 if (list_empty(&dev->mode_config.fb_kernel_list)) {
523 ret = (*fb_create)(dev, fb_width, fb_height, surface_width,
524 surface_height, &fb);
525 if (ret)
526 return -EINVAL;
527 new_fb = 1;
528 } else {
529 fb = list_first_entry(&dev->mode_config.fb_kernel_list,
530 struct drm_framebuffer, filp_head);
531
532 /* if someone hotplugs something bigger than we have already allocated, we are pwned.
533 As really we can't resize an fbdev that is in the wild currently due to fbdev
534 not really being designed for the lower layers moving stuff around under it.
535 - so in the grand style of things - punt. */
536 if ((fb->width < surface_width) ||
537 (fb->height < surface_height)) {
538 DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
539 return -EINVAL;
540 }
541 }
542
543 info = fb->fbdev;
544 fb_helper = info->par;
545
546 crtc_count = 0;
547 /* okay we need to setup new connector sets in the crtcs */
548 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
549 modeset = &fb_helper->crtc_info[crtc_count].mode_set;
550 modeset->fb = fb;
551 conn_count = 0;
552 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
553 if (connector->encoder)
554 if (connector->encoder->crtc == modeset->crtc) {
555 modeset->connectors[conn_count] = connector;
556 conn_count++;
557 if (conn_count > fb_helper->conn_limit)
558 BUG();
559 }
560 }
561
562 for (i = conn_count; i < fb_helper->conn_limit; i++)
563 modeset->connectors[i] = NULL;
564
565 modeset->crtc = crtc;
566 crtc_count++;
567
568 modeset->num_connectors = conn_count;
569 if (modeset->crtc->desired_mode) {
570 if (modeset->mode)
571 drm_mode_destroy(dev, modeset->mode);
572 modeset->mode = drm_mode_duplicate(dev,
573 modeset->crtc->desired_mode);
574 }
575 }
576 fb_helper->crtc_count = crtc_count;
577 fb_helper->fb = fb;
578
579 if (new_fb) {
580 info->var.pixclock = -1;
581 if (register_framebuffer(info) < 0)
582 return -EINVAL;
583 } else {
584 drm_fb_helper_set_par(info);
585 }
586 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
587 info->fix.id);
588
589 /* Switch back to kernel console on panic */
590 /* multi card linked list maybe */
591 if (list_empty(&kernel_fb_helper_list)) {
592 printk(KERN_INFO "registered panic notifier\n");
593 atomic_notifier_chain_register(&panic_notifier_list,
594 &paniced);
595 register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
596 }
597 list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
598 return 0;
599}
600EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
601
602void drm_fb_helper_free(struct drm_fb_helper *helper)
603{
604 list_del(&helper->kernel_fb_list);
605 if (list_empty(&kernel_fb_helper_list)) {
606 printk(KERN_INFO "unregistered panic notifier\n");
607 atomic_notifier_chain_unregister(&panic_notifier_list,
608 &paniced);
609 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
610 }
611 drm_fb_helper_crtc_free(helper);
612}
613EXPORT_SYMBOL(drm_fb_helper_free);
614
615void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch)
616{
617 info->fix.type = FB_TYPE_PACKED_PIXELS;
618 info->fix.visual = FB_VISUAL_TRUECOLOR;
619 info->fix.type_aux = 0;
620 info->fix.xpanstep = 1; /* doing it in hw */
621 info->fix.ypanstep = 1; /* doing it in hw */
622 info->fix.ywrapstep = 0;
3420e742 623 info->fix.accel = FB_ACCEL_NONE;
785b93ef
DA
624 info->fix.type_aux = 0;
625
626 info->fix.line_length = pitch;
627 return;
628}
629EXPORT_SYMBOL(drm_fb_helper_fill_fix);
630
631void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb,
632 uint32_t fb_width, uint32_t fb_height)
633{
634 info->pseudo_palette = fb->pseudo_palette;
635 info->var.xres_virtual = fb->width;
636 info->var.yres_virtual = fb->height;
637 info->var.bits_per_pixel = fb->bits_per_pixel;
638 info->var.xoffset = 0;
639 info->var.yoffset = 0;
640 info->var.activate = FB_ACTIVATE_NOW;
641 info->var.height = -1;
642 info->var.width = -1;
643
644 switch (fb->depth) {
645 case 8:
646 info->var.red.offset = 0;
647 info->var.green.offset = 0;
648 info->var.blue.offset = 0;
649 info->var.red.length = 8; /* 8bit DAC */
650 info->var.green.length = 8;
651 info->var.blue.length = 8;
652 info->var.transp.offset = 0;
653 info->var.transp.length = 0;
654 break;
655 case 15:
656 info->var.red.offset = 10;
657 info->var.green.offset = 5;
658 info->var.blue.offset = 0;
659 info->var.red.length = 5;
660 info->var.green.length = 5;
661 info->var.blue.length = 5;
662 info->var.transp.offset = 15;
663 info->var.transp.length = 1;
664 break;
665 case 16:
666 info->var.red.offset = 11;
667 info->var.green.offset = 5;
668 info->var.blue.offset = 0;
669 info->var.red.length = 5;
670 info->var.green.length = 6;
671 info->var.blue.length = 5;
672 info->var.transp.offset = 0;
673 break;
674 case 24:
675 info->var.red.offset = 16;
676 info->var.green.offset = 8;
677 info->var.blue.offset = 0;
678 info->var.red.length = 8;
679 info->var.green.length = 8;
680 info->var.blue.length = 8;
681 info->var.transp.offset = 0;
682 info->var.transp.length = 0;
683 break;
684 case 32:
685 info->var.red.offset = 16;
686 info->var.green.offset = 8;
687 info->var.blue.offset = 0;
688 info->var.red.length = 8;
689 info->var.green.length = 8;
690 info->var.blue.length = 8;
691 info->var.transp.offset = 24;
692 info->var.transp.length = 8;
693 break;
694 default:
695 break;
696 }
697
698 info->var.xres = fb_width;
699 info->var.yres = fb_height;
700}
701EXPORT_SYMBOL(drm_fb_helper_fill_var);