aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fb_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c138
1 files changed, 106 insertions, 32 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 819ddcbfcce5..23dc9c115fd9 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -454,6 +454,96 @@ 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
505int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
506{
507 struct drm_fb_helper *fb_helper = info->par;
508 struct drm_device *dev = fb_helper->dev;
509 u16 *red, *green, *blue, *transp;
510 struct drm_crtc *crtc;
511 int i, rc = 0;
512 int start;
513
514 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
515 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
516 for (i = 0; i < fb_helper->crtc_count; i++) {
517 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
518 break;
519 }
520 if (i == fb_helper->crtc_count)
521 continue;
522
523 red = cmap->red;
524 green = cmap->green;
525 blue = cmap->blue;
526 transp = cmap->transp;
527 start = cmap->start;
528
529 for (i = 0; i < cmap->len; i++) {
530 u16 hred, hgreen, hblue, htransp = 0xffff;
531
532 hred = *red++;
533 hgreen = *green++;
534 hblue = *blue++;
535
536 if (transp)
537 htransp = *transp++;
538
539 setcolreg(crtc, hred, hgreen, hblue, start++, info);
540 }
541 crtc_funcs->load_lut(crtc);
542 }
543 return rc;
544}
545EXPORT_SYMBOL(drm_fb_helper_setcmap);
546
457int drm_fb_helper_setcolreg(unsigned regno, 547int drm_fb_helper_setcolreg(unsigned regno,
458 unsigned red, 548 unsigned red,
459 unsigned green, 549 unsigned green,
@@ -466,9 +556,11 @@ int drm_fb_helper_setcolreg(unsigned regno,
466 struct drm_crtc *crtc; 556 struct drm_crtc *crtc;
467 int i; 557 int i;
468 558
469 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 559 if (regno > 255)
470 struct drm_framebuffer *fb = fb_helper->fb; 560 return 1;
471 561
562 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
563 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
472 for (i = 0; i < fb_helper->crtc_count; i++) { 564 for (i = 0; i < fb_helper->crtc_count; i++) {
473 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) 565 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
474 break; 566 break;
@@ -476,35 +568,9 @@ int drm_fb_helper_setcolreg(unsigned regno,
476 if (i == fb_helper->crtc_count) 568 if (i == fb_helper->crtc_count)
477 continue; 569 continue;
478 570
479 if (regno > 255)
480 return 1;
481
482 if (fb->depth == 8) {
483 fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
484 return 0;
485 }
486 571
487 if (regno < 16) { 572 setcolreg(crtc, red, green, blue, regno, info);
488 switch (fb->depth) { 573 crtc_funcs->load_lut(crtc);
489 case 15:
490 fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
491 ((green & 0xf800) >> 6) |
492 ((blue & 0xf800) >> 11);
493 break;
494 case 16:
495 fb->pseudo_palette[regno] = (red & 0xf800) |
496 ((green & 0xfc00) >> 5) |
497 ((blue & 0xf800) >> 11);
498 break;
499 case 24:
500 case 32:
501 fb->pseudo_palette[regno] =
502 (((red >> 8) & 0xff) << info->var.red.offset) |
503 (((green >> 8) & 0xff) << info->var.green.offset) |
504 (((blue >> 8) & 0xff) << info->var.blue.offset);
505 break;
506 }
507 }
508 } 574 }
509 return 0; 575 return 0;
510} 576}
@@ -674,6 +740,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
674EXPORT_SYMBOL(drm_fb_helper_pan_display); 740EXPORT_SYMBOL(drm_fb_helper_pan_display);
675 741
676int 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,
677 int (*fb_create)(struct drm_device *dev, 744 int (*fb_create)(struct drm_device *dev,
678 uint32_t fb_width, 745 uint32_t fb_width,
679 uint32_t fb_height, 746 uint32_t fb_height,
@@ -696,6 +763,11 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
696 struct drm_fb_helper *fb_helper; 763 struct drm_fb_helper *fb_helper;
697 uint32_t surface_depth = 24, surface_bpp = 32; 764 uint32_t surface_depth = 24, surface_bpp = 32;
698 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 }
699 /* 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 */
700 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 772 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
701 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;
@@ -851,10 +923,12 @@ void drm_fb_helper_free(struct drm_fb_helper *helper)
851} 923}
852EXPORT_SYMBOL(drm_fb_helper_free); 924EXPORT_SYMBOL(drm_fb_helper_free);
853 925
854void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch) 926void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
927 uint32_t depth)
855{ 928{
856 info->fix.type = FB_TYPE_PACKED_PIXELS; 929 info->fix.type = FB_TYPE_PACKED_PIXELS;
857 info->fix.visual = FB_VISUAL_TRUECOLOR; 930 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
931 FB_VISUAL_DIRECTCOLOR;
858 info->fix.type_aux = 0; 932 info->fix.type_aux = 0;
859 info->fix.xpanstep = 1; /* doing it in hw */ 933 info->fix.xpanstep = 1; /* doing it in hw */
860 info->fix.ypanstep = 1; /* doing it in hw */ 934 info->fix.ypanstep = 1; /* doing it in hw */