aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fb_helper.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-10-05 23:54:01 -0400
committerDave Airlie <airlied@redhat.com>2009-10-05 23:54:01 -0400
commitb8c00ac5b50b54491657f8b6740db1df50149944 (patch)
treeb4cfbc0dbb5ba063bcc933d7339504b80dc5c61c /drivers/gpu/drm/drm_fb_helper.c
parent068143d38804825d59d951a192cfadd2e22f457d (diff)
drm/fb: add more correct 8/16/24/32 bpp fb support.
The previous patches had some unwanted side effects, I've fixed the lack of 32bpp working, and fixed up 16bpp so it should also work. this also adds the interface to allow the driver to set a preferred console depth so for example low memory rn50 can set it to 8bpp. It also catches 24bpp on cards that can't do it and forces 32bpp. Tested on r100/r600/i945. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c95
1 files changed, 62 insertions, 33 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3746bd2f0f08..23dc9c115fd9 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -454,6 +454,54 @@ out_free:
454} 454}
455EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); 455EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
456 456
457static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
458 u16 blue, u16 regno, struct fb_info *info)
459{
460 struct drm_fb_helper *fb_helper = info->par;
461 struct drm_framebuffer *fb = fb_helper->fb;
462 int pindex;
463
464 pindex = regno;
465
466 if (fb->bits_per_pixel == 16) {
467 pindex = regno << 3;
468
469 if (fb->depth == 16 && regno > 63)
470 return;
471 if (fb->depth == 15 && regno > 31)
472 return;
473
474 if (fb->depth == 16) {
475 u16 r, g, b;
476 int i;
477 if (regno < 32) {
478 for (i = 0; i < 8; i++)
479 fb_helper->funcs->gamma_set(crtc, red,
480 green, blue, pindex + i);
481 }
482
483 fb_helper->funcs->gamma_get(crtc, &r,
484 &g, &b,
485 pindex >> 1);
486
487 for (i = 0; i < 4; i++)
488 fb_helper->funcs->gamma_set(crtc, r,
489 green, b,
490 (pindex >> 1) + i);
491 }
492 }
493
494 if (fb->depth != 16)
495 fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
496
497 if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
498 ((u32 *) fb->pseudo_palette)[regno] =
499 (regno << info->var.red.offset) |
500 (regno << info->var.green.offset) |
501 (regno << info->var.blue.offset);
502 }
503}
504
457int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) 505int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
458{ 506{
459 struct drm_fb_helper *fb_helper = info->par; 507 struct drm_fb_helper *fb_helper = info->par;
@@ -488,7 +536,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
488 if (transp) 536 if (transp)
489 htransp = *transp++; 537 htransp = *transp++;
490 538
491 fb_helper->funcs->gamma_set(crtc, hred, hgreen, hblue, start++); 539 setcolreg(crtc, hred, hgreen, hblue, start++, info);
492 } 540 }
493 crtc_funcs->load_lut(crtc); 541 crtc_funcs->load_lut(crtc);
494 } 542 }
@@ -508,9 +556,11 @@ int drm_fb_helper_setcolreg(unsigned regno,
508 struct drm_crtc *crtc; 556 struct drm_crtc *crtc;
509 int i; 557 int i;
510 558
511 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 559 if (regno > 255)
512 struct drm_framebuffer *fb = fb_helper->fb; 560 return 1;
513 561
562 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
563 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
514 for (i = 0; i < fb_helper->crtc_count; i++) { 564 for (i = 0; i < fb_helper->crtc_count; i++) {
515 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) 565 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
516 break; 566 break;
@@ -518,36 +568,9 @@ int drm_fb_helper_setcolreg(unsigned regno,
518 if (i == fb_helper->crtc_count) 568 if (i == fb_helper->crtc_count)
519 continue; 569 continue;
520 570
521 if (regno > 255)
522 return 1;
523
524 if (fb->depth == 8) {
525 fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
526 return 0;
527 }
528 571
529 if (regno < 16) { 572 setcolreg(crtc, red, green, blue, regno, info);
530 u32 *pal = fb->pseudo_palette; 573 crtc_funcs->load_lut(crtc);
531 switch (fb->depth) {
532 case 15:
533 pal[regno] = ((red & 0xf800) >> 1) |
534 ((green & 0xf800) >> 6) |
535 ((blue & 0xf800) >> 11);
536 break;
537 case 16:
538 pal[regno] = (red & 0xf800) |
539 ((green & 0xfc00) >> 5) |
540 ((blue & 0xf800) >> 11);
541 break;
542 case 24:
543 case 32:
544 pal[regno] =
545 (((red >> 8) & 0xff) << info->var.red.offset) |
546 (((green >> 8) & 0xff) << info->var.green.offset) |
547 (((blue >> 8) & 0xff) << info->var.blue.offset);
548 break;
549 }
550 }
551 } 574 }
552 return 0; 575 return 0;
553} 576}
@@ -717,6 +740,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
717EXPORT_SYMBOL(drm_fb_helper_pan_display); 740EXPORT_SYMBOL(drm_fb_helper_pan_display);
718 741
719int drm_fb_helper_single_fb_probe(struct drm_device *dev, 742int drm_fb_helper_single_fb_probe(struct drm_device *dev,
743 int preferred_bpp,
720 int (*fb_create)(struct drm_device *dev, 744 int (*fb_create)(struct drm_device *dev,
721 uint32_t fb_width, 745 uint32_t fb_width,
722 uint32_t fb_height, 746 uint32_t fb_height,
@@ -739,6 +763,11 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
739 struct drm_fb_helper *fb_helper; 763 struct drm_fb_helper *fb_helper;
740 uint32_t surface_depth = 24, surface_bpp = 32; 764 uint32_t surface_depth = 24, surface_bpp = 32;
741 765
766 /* if driver picks 8 or 16 by default use that
767 for both depth/bpp */
768 if (preferred_bpp != surface_bpp) {
769 surface_depth = surface_bpp = preferred_bpp;
770 }
742 /* first up get a count of crtcs now in use and new min/maxes width/heights */ 771 /* 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) { 772 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
744 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; 773 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
@@ -899,7 +928,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
899{ 928{
900 info->fix.type = FB_TYPE_PACKED_PIXELS; 929 info->fix.type = FB_TYPE_PACKED_PIXELS;
901 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : 930 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
902 FB_VISUAL_TRUECOLOR; 931 FB_VISUAL_DIRECTCOLOR;
903 info->fix.type_aux = 0; 932 info->fix.type_aux = 0;
904 info->fix.xpanstep = 1; /* doing it in hw */ 933 info->fix.xpanstep = 1; /* doing it in hw */
905 info->fix.ypanstep = 1; /* doing it in hw */ 934 info->fix.ypanstep = 1; /* doing it in hw */